Compare commits

..

No commits in common. "d2a255ad2e6b34661b2510d9bf0d36abc4d817ad" and "4161280b4d6472edf153843d1d5aa0ac42a5e6ea" have entirely different histories.

31 changed files with 403 additions and 767 deletions

403
Cargo.lock generated
View File

@ -2,28 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "ahash"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [
"cfg-if 1.0.0",
"once_cell",
"version_check",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
@ -48,12 +26,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "atty"
version = "0.2.14"
@ -83,97 +55,12 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "borsh"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive",
"hashbrown 0.13.2",
]
[[package]]
name = "borsh-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7"
dependencies = [
"borsh-derive-internal",
"borsh-schema-derive-internal",
"proc-macro-crate",
"proc-macro2 1.0.69",
"syn 1.0.109",
]
[[package]]
name = "borsh-derive-internal"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb"
dependencies = [
"proc-macro2 1.0.69",
"quote 1.0.33",
"syn 1.0.109",
]
[[package]]
name = "borsh-schema-derive-internal"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd"
dependencies = [
"proc-macro2 1.0.69",
"quote 1.0.33",
"syn 1.0.109",
]
[[package]]
name = "bumpalo"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytecheck"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627"
dependencies = [
"bytecheck_derive",
"ptr_meta",
"simdutf8",
]
[[package]]
name = "bytecheck_derive"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61"
dependencies = [
"proc-macro2 1.0.69",
"quote 1.0.33",
"syn 1.0.109",
]
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cassowary"
version = "0.3.0"
@ -250,12 +137,11 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "crptls"
version = "0.2.2"
version = "0.2.0"
dependencies = [
"chrono",
"csv",
"rust_decimal",
"rust_decimal_macros",
"decimal",
"serde",
"serde_derive",
"time",
@ -263,14 +149,13 @@ dependencies = [
[[package]]
name = "cryptools"
version = "0.12.2"
version = "0.12.0"
dependencies = [
"chrono",
"crptls",
"csv",
"decimal",
"dotenv",
"rust_decimal",
"rust_decimal_macros",
"rustyline",
"structopt",
"termion",
@ -298,6 +183,20 @@ dependencies = [
"memchr",
]
[[package]]
name = "decimal"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a8ab77e91baeb15034c3be91e87bff4665c9036216148e4996d9a9f5792114d"
dependencies = [
"bitflags 1.3.2",
"cc",
"libc",
"ord_subset",
"rustc-serialize",
"serde",
]
[[package]]
name = "deranged"
version = "0.3.9"
@ -356,41 +255,6 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash 0.7.6",
]
[[package]]
name = "hashbrown"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash 0.8.3",
]
[[package]]
name = "heck"
version = "0.3.1"
@ -533,27 +397,18 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "ord_subset"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7ce14664caf5b27f5656ff727defd68ae1eb75ef3c4d95259361df1eb376bef"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-crate"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
dependencies = [
"toml",
]
[[package]]
name = "proc-macro2"
version = "0.4.30"
@ -572,26 +427,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2 1.0.69",
"quote 1.0.33",
"syn 1.0.109",
]
[[package]]
name = "quote"
version = "0.6.13"
@ -610,12 +445,6 @@ dependencies = [
"proc-macro2 1.0.69",
]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "radix_trie"
version = "0.2.1"
@ -626,36 +455,6 @@ dependencies = [
"nibble_vec",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
@ -672,67 +471,10 @@ dependencies = [
]
[[package]]
name = "rend"
version = "0.4.1"
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd"
dependencies = [
"bytecheck",
]
[[package]]
name = "rkyv"
version = "0.7.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58"
dependencies = [
"bitvec",
"bytecheck",
"hashbrown 0.12.3",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
"tinyvec",
"uuid",
]
[[package]]
name = "rkyv_derive"
version = "0.7.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d"
dependencies = [
"proc-macro2 1.0.69",
"quote 1.0.33",
"syn 1.0.109",
]
[[package]]
name = "rust_decimal"
version = "1.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd"
dependencies = [
"arrayvec",
"borsh",
"bytes",
"num-traits",
"rand",
"rkyv",
"serde",
"serde_json",
]
[[package]]
name = "rust_decimal_macros"
version = "1.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86444b802de0b10ac5e563b5ddb43b541b9705de4e01a50e82194d2b183c1835"
dependencies = [
"quote 1.0.33",
"rust_decimal",
]
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]]
name = "rustix"
@ -782,12 +524,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.189"
@ -808,23 +544,6 @@ dependencies = [
"syn 2.0.38",
]
[[package]]
name = "serde_json"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "simdutf8"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
[[package]]
name = "smallvec"
version = "1.11.1"
@ -876,17 +595,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2 1.0.69",
"quote 1.0.33",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.38"
@ -898,12 +606,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "termion"
version = "1.5.5"
@ -943,30 +645,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "tui"
version = "0.8.0"
@ -1013,30 +691,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.87"
@ -1187,12 +847,3 @@ name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]

View File

@ -1,8 +1,8 @@
[package]
name = "cryptools"
version = "0.12.2"
version = "0.12.0"
authors = ["scoobybejesus <scoobybejesus@users.noreply.github.com>"]
edition = "2021"
edition = "2018"
description = "Command-line utility for processing cryptocurrency transactions into 'lots' and 'movements'."
[features]
@ -21,8 +21,7 @@ path = "src/main.rs"
[dependencies]
crptls = { path = "crptls" }
csv = "1.3.0"
rust_decimal = "1.32"
rust_decimal_macros = "1.32"
decimal = "2.1.0"
chrono = { version = "0.4.31", features = ["serde"] }
structopt = "0.2.10"
rustyline = "12.0.0"

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
//
// All rights reserved.
//

View File

@ -1,12 +1,11 @@
[package]
name = "crptls"
version = "0.2.2"
version = "0.2.0"
authors = ["scoobybejesus <scoobybejesus@users.noreply.github.com>"]
edition = "2021"
edition = "2018"
[dependencies]
rust_decimal = "1.32"
rust_decimal_macros = "1.32"
decimal = "2.1.0"
chrono = { version = "0.4.31", features = ["serde"] }
csv = "1.3.0"
serde = { version = "1.0.189", features = ["derive"] }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
//
// All rights reserved.
//

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::rc::{Rc, Weak};
@ -8,8 +8,7 @@ use std::collections::HashMap;
use std::error::Error;
use chrono::NaiveDate;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use serde_derive::{Serialize, Deserialize};
use crate::transaction::{Transaction, ActionRecord, Polarity, TxType};
@ -45,9 +44,9 @@ pub struct Account {
impl Account {
pub fn get_sum_of_amts_in_lots(&self) -> Decimal {
pub fn get_sum_of_amts_in_lots(&self) -> d128 {
let lots = self.list_of_lots.borrow();
let mut total_amount = dec!(0);
let mut total_amount = d128!(0);
for lot in lots.iter() {
let sum = lot.get_sum_of_amts_in_lot();
total_amount += sum;
@ -55,9 +54,9 @@ impl Account {
total_amount
}
pub fn get_sum_of_lk_basis_in_lots(&self) -> Decimal {
pub fn get_sum_of_lk_basis_in_lots(&self) -> d128 {
let lots = self.list_of_lots.borrow();
let mut total_amount = dec!(0);
let mut total_amount = d128!(0);
for lot in lots.iter() {
let sum = lot.get_sum_of_lk_basis_in_lot();
total_amount += sum;
@ -65,9 +64,9 @@ impl Account {
total_amount
}
pub fn get_sum_of_orig_basis_in_lots(&self) -> Decimal {
pub fn get_sum_of_orig_basis_in_lots(&self) -> d128 {
let lots = self.list_of_lots.borrow();
let mut total_amount = dec!(0);
let mut total_amount = d128!(0);
for lot in lots.iter() {
let sum = lot.get_sum_of_orig_basis_in_lot();
total_amount += sum;
@ -80,7 +79,7 @@ impl Account {
let mut count = 0;
for lot in self.list_of_lots.borrow().iter() {
if lot.get_sum_of_amts_in_lot() > dec!(0) {
if lot.get_sum_of_amts_in_lot() > d128!(0) {
count += 1
}
}
@ -103,20 +102,20 @@ pub struct Lot {
}
impl Lot {
pub fn get_sum_of_amts_in_lot(&self) -> Decimal {
let mut amts = dec!(0);
pub fn get_sum_of_amts_in_lot(&self) -> d128 {
let mut amts = d128!(0);
self.movements.borrow().iter().for_each(|movement| amts += movement.amount);
amts
}
pub fn get_sum_of_lk_basis_in_lot(&self) -> Decimal {
let mut amts = dec!(0);
pub fn get_sum_of_lk_basis_in_lot(&self) -> d128 {
let mut amts = d128!(0);
self.movements.borrow().iter().for_each(|movement| amts += movement.cost_basis_lk.get());
amts
}
pub fn get_sum_of_orig_basis_in_lot(&self) -> Decimal {
let mut amts = dec!(0);
pub fn get_sum_of_orig_basis_in_lot(&self) -> d128 {
let mut amts = d128!(0);
self.movements.borrow().iter().for_each(|movement| amts += movement.cost_basis.get());
amts
}
@ -124,18 +123,18 @@ impl Lot {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Movement {
pub amount: Decimal,
pub amount: d128,
pub date_as_string: String,
pub date: NaiveDate,
pub transaction_key: u32,
pub action_record_key: u32,
pub cost_basis: Cell<Decimal>, // Initialized with 0. Set in add_cost_basis_to_movements()
pub ratio_of_amt_to_incoming_mvmts_in_a_r: Decimal, // Set in process_multiple_incoming_lots_and_mvmts() and incoming flow dual actionrecord transactions
pub ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell<Decimal>, // Set in wrap_mvmt_and_push()
pub cost_basis: Cell<d128>, // Initialized with 0. Set in add_cost_basis_to_movements()
pub ratio_of_amt_to_incoming_mvmts_in_a_r: d128, // Set in process_multiple_incoming_lots_and_mvmts() and incoming flow dual actionrecord transactions
pub ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell<d128>, // Set in wrap_mvmt_and_push()
pub lot_num: u32,
pub proceeds: Cell<Decimal>, // Initialized with 0. Set in add_proceeds_to_movements()
pub proceeds_lk: Cell<Decimal>,
pub cost_basis_lk: Cell<Decimal>,
pub proceeds: Cell<d128>, // Initialized with 0. Set in add_proceeds_to_movements()
pub proceeds_lk: Cell<d128>,
pub cost_basis_lk: Cell<d128>,
}
impl Movement {
@ -155,7 +154,7 @@ impl Movement {
&self,
acct_map: &HashMap<u16, Account>,
ar_map: &HashMap<u32, ActionRecord>
) -> Decimal {
) -> d128 {
let lot = self.get_lot(acct_map, ar_map);
let list_of_lot_mvmts = lot.movements.borrow();
@ -168,7 +167,7 @@ impl Movement {
&self,
acct_map: &HashMap<u16, Account>,
ar_map: &HashMap<u32, ActionRecord>
) -> Decimal {
) -> d128 {
let lot = self.get_lot(acct_map, ar_map);
let list_of_lot_mvmts = lot.movements.borrow();
@ -181,7 +180,7 @@ impl Movement {
&self,
acct_map: &HashMap<u16, Account>,
ar_map: &HashMap<u32, ActionRecord>
) -> Decimal {
) -> d128 {
let lot = self.get_lot(acct_map, ar_map);
let list_of_lot_mvmts = lot.movements.borrow();
@ -190,11 +189,11 @@ impl Movement {
cost_basis
}
pub fn get_lk_gain_or_loss(&self) -> Decimal {
pub fn get_lk_gain_or_loss(&self) -> d128 {
self.proceeds_lk.get() + self.cost_basis_lk.get()
}
pub fn get_orig_gain_or_loss(&self) -> Decimal {
pub fn get_orig_gain_or_loss(&self) -> d128 {
self.proceeds.get() + self.cost_basis.get()
}
@ -256,7 +255,7 @@ impl Movement {
raw_accts: &HashMap<u16, RawAccount>,
acct_map: &HashMap<u16, Account>,
txns_map: &HashMap<u32, Transaction>,
)-> Result<Decimal, Box<dyn Error>> { // Returns 0 or positive number
)-> Result<d128, Box<dyn Error>> { // Returns 0 or positive number
let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?");
@ -269,10 +268,10 @@ impl Movement {
if ar.direction() == Polarity::Incoming {
Ok(-self.proceeds_lk.get())
}
else { Ok(dec!(0)) }
else { Ok(d128!(0)) }
}
TxType::Exchange => { Ok(dec!(0)) }
TxType::ToSelf => { Ok(dec!(0)) }
TxType::Exchange => { Ok(d128!(0)) }
TxType::ToSelf => { Ok(d128!(0)) }
}
}
@ -282,7 +281,7 @@ impl Movement {
raw_accts: &HashMap<u16, RawAccount>,
acct_map: &HashMap<u16, Account>,
txns_map: &HashMap<u32, Transaction>,
)-> Result<Decimal, Box<dyn Error>> { // Returns 0 or negative number
)-> Result<d128, Box<dyn Error>> { // Returns 0 or negative number
let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?");
@ -299,7 +298,7 @@ impl Movement {
if raw_acct.is_margin {
Ok(dec!(0))
Ok(d128!(0))
} else {
@ -307,10 +306,10 @@ impl Movement {
Ok(expense)
}
}
else { Ok(dec!(0)) }
else { Ok(d128!(0)) }
}
TxType::Exchange => { Ok(dec!(0)) }
TxType::ToSelf => { Ok(dec!(0)) }
TxType::Exchange => { Ok(d128!(0)) }
TxType::ToSelf => { Ok(d128!(0)) }
}
}
@ -326,7 +325,7 @@ impl Movement {
let direction: String;
if self.amount > dec!(0) {
if self.amount > d128!(0) {
direction = "In".to_string();
} else {
direction = "Out".to_string()

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::path::PathBuf;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::fmt;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::rc::Rc;
@ -6,8 +6,7 @@ use std::cell::{RefCell, Ref, Cell};
use std::collections::HashMap;
use std::error::Error;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use crate::core_functions::ImportProcessParameters;
use crate::transaction::{Transaction, ActionRecord, TxType, Polarity, TxHasMargin};
@ -119,8 +118,8 @@ pub(crate) fn create_lots_and_movements(
if !base_acct_lot_list.is_empty() && !quote_acct_lot_list.is_empty() {
// Since we know there has been activity, we set the bool variable above according to whether the `account`
// balances are both zero.
let base_balance_is_zero = base_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == dec!(0);
let quote_balance_is_zero = quote_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == dec!(0);
let base_balance_is_zero = base_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == d128!(0);
let quote_balance_is_zero = quote_acct_lot_list.last().unwrap().get_sum_of_amts_in_lot() == d128!(0);
if base_balance_is_zero && quote_balance_is_zero {
acct_balances_are_zero = true
} else {
@ -181,13 +180,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: base_ar_idx,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: base_lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
let raw_base_acct = raw_acct_map.get(&base_acct.raw_key).unwrap();
wrap_mvmt_and_push(
@ -204,13 +203,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: quote_ar_idx,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: quote_lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
let raw_quote_acct = raw_acct_map.get(&quote_acct.raw_key).unwrap();
wrap_mvmt_and_push(
@ -275,13 +274,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(
whole_mvmt,
@ -329,13 +328,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(
whole_mvmt,
@ -442,13 +441,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot_to_use.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// Just a last minute check that a home currency `action record` isn't being handled here
@ -508,13 +507,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(
mvmt,
@ -554,13 +553,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// The more complicated case is the dual-`action record` `flow` `transaction`.
@ -583,7 +582,7 @@ pub(crate) fn create_lots_and_movements(
// of the margin trade that is now ending in a profit. And `total_positive_amounts` accounts for the total
// amount of those margin-buys.
let mut positive_mvmt_list: Vec<Rc<Movement>> = [].to_vec();
let mut total_positive_amounts = dec!(0);
let mut total_positive_amounts = d128!(0);
// This is necessary to find the base account, because the margin-buys are reflected in this account.
let (base_acct_key, quote_acct_key) = get_base_and_quote_acct_for_dual_actionrecord_flow_tx(
@ -599,7 +598,7 @@ pub(crate) fn create_lots_and_movements(
// It should be apparent that the relevant `lot` has been selected, and its `movement` are now iterated
// over for capturing its `movement`s (for their date) and adding up their amounts.
for base_acct_mvmt in base_acct_lot.movements.borrow().iter() {
if base_acct_mvmt.amount > dec!(0) {
if base_acct_mvmt.amount > d128!(0) {
// println!("In lot# {}, positive mvmt amount: {} {},",
// base_acct_lot.lot_number,
// mvmt.borrow().amount,
@ -611,8 +610,8 @@ pub(crate) fn create_lots_and_movements(
// These variables track relevant usage in the following for-loop. These are used after the for-loop
// when creating the final `movement`.
let mut amounts_used = dec!(0);
let mut percentages_used = dec!(0);
let mut amounts_used = d128!(0);
let mut percentages_used = d128!(0);
// Here, the margin-buys are iterated over while creating proportionally-sized new `movement`s.
// Note that this for-loop excludes the final positive `movement` because rounding must be taken into
@ -638,13 +637,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: percentage_used,
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: inner_lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(
inner_mvmt,
@ -678,13 +677,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: round_d128_1e8(&(dec!(1.0) - percentages_used)),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: round_d128_1e8(&(d128!(1.0) - percentages_used)),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// Back to "base case" style treatment, if this is an incoming dual-`action record` `flow` `transaction`, but either
@ -707,13 +706,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
}
}
@ -782,13 +781,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
}
}
@ -812,13 +811,13 @@ pub(crate) fn create_lots_and_movements(
date: txn.date,
transaction_key: txn_num,
action_record_key: *ar_num,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
}
// The `lot` and `whole_mvmt` variables have been initialized/assigned
@ -961,7 +960,7 @@ fn wrap_mvmt_and_push(
/// that was pushed to the previous `lot`), and recursively check...
fn fit_into_lots(
mvmt_to_fit: Movement,
amt_to_fit: Decimal,
amt_to_fit: d128,
list_of_lots_to_use: RefCell<Vec<Rc<Lot>>>,
vec_of_ordered_index_values: Vec<usize>,
index_position: usize,
@ -979,7 +978,7 @@ fn fit_into_lots(
if vec_of_ordered_index_values.len() == current_index_position {
println!("FATAL: Txn {} on {} spending {} {} has run out of lots to spend from.",
mvmt_to_fit.transaction_key, mvmt_to_fit.date_as_string, ar.amount, raw_acct.ticker);
let bal = if acct.get_sum_of_amts_in_lots() == dec!(0) { "0.00000000".to_string() }
let bal = if acct.get_sum_of_amts_in_lots() == d128!(0) { "0.00000000".to_string() }
else { acct.get_sum_of_amts_in_lots().to_string() };
println!("Account balance is only: {}", bal);
std::process::exit(1);
@ -988,15 +987,15 @@ fn fit_into_lots(
// Get the `lot`, and then get its balance to see how much room there is
let lot_index = vec_of_ordered_index_values[current_index_position];
let lot = acct.list_of_lots.borrow()[lot_index].clone();
let mut sum_of_mvmts_in_lot: Decimal = dec!(0.0);
let mut sum_of_mvmts_in_lot: d128 = d128!(0.0);
for movement in lot.movements.borrow().iter() {
sum_of_mvmts_in_lot += movement.amount;
}
assert!(sum_of_mvmts_in_lot >= dec!(0.0));
assert!(sum_of_mvmts_in_lot >= d128!(0.0));
// If the `lot` is "full", try the next.
if sum_of_mvmts_in_lot == dec!(0.0) {
if sum_of_mvmts_in_lot == d128!(0.0) {
current_index_position += 1;
@ -1014,15 +1013,15 @@ fn fit_into_lots(
return;
}
assert!(sum_of_mvmts_in_lot > dec!(0.0));
assert!(sum_of_mvmts_in_lot > d128!(0.0));
// If `remainder_amt_to_recurse` is positive, it means the `lot` balance exceeded `amt_to_fit`,
// therefore, the amount completely fits in the `lot`. If negative, it is passed as the `amt_to_fit`
// for the next round of recursion.
let remainder_amt_to_recurse = (amt_to_fit + sum_of_mvmts_in_lot).round_dp(8);
let remainder_amt_to_recurse = (amt_to_fit + sum_of_mvmts_in_lot).reduce();
// If the remainder fits, the `movement` is wrapped/pushed, and the recursion is complete.
if remainder_amt_to_recurse >= dec!(0.0) {
if remainder_amt_to_recurse >= d128!(0.0) {
let remainder_mvmt_that_fits: Movement = Movement {
amount: amt_to_fit,
@ -1041,7 +1040,7 @@ fn fit_into_lots(
// The amt_to_fit doesn't completely fit in the present `lot`, but some does. Create a `movement` that will fit.
let mvmt_that_fits_in_lot: Movement = Movement {
amount: (-sum_of_mvmts_in_lot).round_dp(8),
amount: (-sum_of_mvmts_in_lot).reduce(),
lot_num: lot.lot_number,
..mvmt_to_fit.clone()
};
@ -1058,7 +1057,7 @@ fn fit_into_lots(
// After applying some of the `amt_to_fit` to the `lot`, increment the index, take the remainder, and recurse
fit_into_lots(
mvmt_to_fit,
remainder_amt_to_recurse.round_dp(8), // This was updated before recursing
remainder_amt_to_recurse.reduce(), // This was updated before recursing
list_of_lots_to_use,
vec_of_ordered_index_values,
current_index_position, // This was updated before recursing
@ -1083,12 +1082,13 @@ fn process_multiple_incoming_lots_and_mvmts(
raw_acct: &RawAccount,
) {
let round_to_places = d128::from(1).scaleb(d128::from(-8));
let txn = txns_map.get(&txn_num).expect("Couldn't get txn. Tx num invalid?");
let acct_of_incoming_ar = acct_map.get(&incoming_ar.account_key).unwrap();
let mut all_but_last_incoming_mvmt_amt = dec!(0.0);
let mut all_but_last_incoming_mvmt_ratio = dec!(0.0);
let mut all_but_last_incoming_mvmt_amt = d128!(0.0);
let mut all_but_last_incoming_mvmt_ratio = d128!(0.0);
// println!("Txn date: {}. Outgoing mvmts: {}, Outgoing amount: {}", txn.date, outgoing_ar.movements.borrow().len(), outgoing_ar.amount);
let list_of_mvmts_of_outgoing_ar = outgoing_ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map);
let list_of_mvmts_of_outgoing_ar_len = list_of_mvmts_of_outgoing_ar.len();
@ -1099,10 +1099,10 @@ fn process_multiple_incoming_lots_and_mvmts(
// println!("Ratio of outgoing amt to total actionrecord amt: {:.8}", ratio_of_outgoing_to_total_ar);
let tentative_incoming_amt = ratio_of_outgoing_mvmt_to_total_ar * incoming_ar.amount;
// println!("Unrounded incoming amt: {}", tentative_incoming_amt);
let corresponding_incoming_amt = tentative_incoming_amt.round_dp(8);
let corresponding_incoming_amt = tentative_incoming_amt.quantize(round_to_places);
// println!("Rounded incoming amt: {}", corresponding_incoming_amt);
if corresponding_incoming_amt == dec!(0) { continue } // Due to rounding, this could be zero.
assert!(corresponding_incoming_amt > dec!(0.0));
if corresponding_incoming_amt == d128!(0) { continue } // Due to rounding, this could be zero.
assert!(corresponding_incoming_amt > d128!(0.0));
let this_acct = acct_of_incoming_ar;
let length_of_list_of_lots: usize = this_acct.list_of_lots.borrow().len();
let inherited_date = outgoing_mvmt.get_lot(acct_map, ar_map).date_of_first_mvmt_in_lot;
@ -1119,18 +1119,18 @@ fn process_multiple_incoming_lots_and_mvmts(
)
;
let incoming_mvmt = Movement {
amount: corresponding_incoming_amt.round_dp(8),
amount: corresponding_incoming_amt.reduce(),
date_as_string: txn.date_as_string.clone(),
date: txn.date,
transaction_key: txn_num,
action_record_key: incoming_ar.self_ar_key,
cost_basis: Cell::new(dec!(0.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: round_d128_1e8(&ratio_of_outgoing_mvmt_to_total_ar),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: inner_lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// println!("From first set of incoming movements, amount: {} {} to account: {}",
// incoming_mvmt.amount, acct_incoming_ar.ticker, acct_incoming_ar.account_num);
@ -1147,7 +1147,7 @@ fn process_multiple_incoming_lots_and_mvmts(
}
// Second iteration, for final movement
let corresponding_incoming_amt = incoming_ar.amount - all_but_last_incoming_mvmt_amt;
assert!(corresponding_incoming_amt > dec!(0.0));
assert!(corresponding_incoming_amt > d128!(0.0));
let this_acct = acct_of_incoming_ar;
let length_of_list_of_lots = this_acct.list_of_lots.borrow().len();
let inherited_date = final_og_mvmt.get_lot(acct_map, ar_map).date_of_first_mvmt_in_lot;
@ -1164,18 +1164,18 @@ fn process_multiple_incoming_lots_and_mvmts(
)
;
let incoming_mvmt = Movement {
amount: corresponding_incoming_amt.round_dp(8),
amount: corresponding_incoming_amt.reduce(),
date_as_string: txn.date_as_string.clone(),
date: txn.date,
transaction_key: txn_num,
action_record_key: incoming_ar.self_ar_key,
cost_basis: Cell::new(dec!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: dec!(1.0) - all_but_last_incoming_mvmt_ratio,
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(dec!(1.0)),
cost_basis: Cell::new(d128!(0.0)),
ratio_of_amt_to_incoming_mvmts_in_a_r: d128!(1.0) - all_but_last_incoming_mvmt_ratio,
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(dec!(0.0)),
proceeds_lk: Cell::new(dec!(0.0)),
cost_basis_lk: Cell::new(dec!(0.0)),
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// println!("Final incoming mvmt for this actionrecord, amount: {} {} to account: {}",
// incoming_mvmt.amount, acct_incoming_ar.ticker, acct_incoming_ar.account_num);

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;
@ -9,8 +9,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use chrono::NaiveDate;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use crate::transaction::{Transaction, ActionRecord};
use crate::account::{Account, RawAccount};
@ -194,30 +193,24 @@ fn import_transactions(
let account_key = acct_idx as u16;
let amount_str = field.replace(",", "");
let amount = match amount_str.parse::<Decimal>() {
Ok(x) => x,
Err(e) => {
println!("FATAL: Couldn't convert amount to d128 for transaction:\n{:#?}", record);
println!("Error: {}", e);
std::process::exit(1);}
};
let mut amount = amount_str.parse::<d128>().unwrap();
// When parsing to a d128, it won't error; rather it'll return a NaN. It must now check for NaN,
// and, if found, attempt to sanitize. These checks will convert accounting/comma format to the expected
// format by removing parentheses from negatives and adding a minus sign in the front. It will also
// attempt to remove empty spaces and currency symbols or designations (e.g. $ or USD).
// if amount.is_none() {
// let b = sanitize_string_for_d128_parsing_basic(field).parse::<Decimal>().unwrap();
// amount = b;
// };
// if amount.is_none() {
// let c = sanitize_string_for_d128_parsing_full(field).parse::<Decimal>().unwrap();
// amount = c;
// };
// if amount.is_none() {
// println!("FATAL: Couldn't convert amount to d128 for transaction:\n{:#?}", record);
// std::process::exit(1);
// }
if amount.is_nan() {
let b = sanitize_string_for_d128_parsing_basic(field).parse::<d128>().unwrap();
amount = b;
};
if amount.is_nan() {
let c = sanitize_string_for_d128_parsing_full(field).parse::<d128>().unwrap();
amount = c;
};
if amount.is_nan() {
println!("FATAL: Couldn't convert amount to d128 for transaction:\n{:#?}", record);
std::process::exit(1);
}
let amount_rounded = round_d128_1e8(&amount);
if amount != amount_rounded { changed_action_records += 1; changed_txn_num.push(this_tx_number); }
@ -230,7 +223,7 @@ fn import_transactions(
movements: RefCell::new([].to_vec()),
};
if amount > dec!(0.0) {
if amount > d128!(0.0) {
incoming_ar = Some(action_record);
incoming_ar_num = Some(this_ar_number);
action_records_map_keys_vec.push(incoming_ar_num.unwrap())
@ -262,52 +255,52 @@ fn import_transactions(
// The Decimal::d128 implementation of FromStr calls into a C library, and that lib hasn't
// been reviewed (by me), but it is thought/hoped to follow similar parsing conventions,
// though there's no guarantee. Nevertheless, the above notes *appear* to hold true for d128.
// fn sanitize_string_for_d128_parsing_basic(field: &str) -> String {
fn sanitize_string_for_d128_parsing_basic(field: &str) -> String {
// // First, remove commas.
// let no_comma_string = field.replace(",", "");
// let almost_done = no_comma_string.replace(" ", "");
// First, remove commas.
let no_comma_string = field.replace(",", "");
let almost_done = no_comma_string.replace(" ", "");
// // Next, if ASCII (better be), check for accounting formatting
// if almost_done.is_ascii() {
// if almost_done.as_bytes()[0] == "(".as_bytes()[0] {
// let half_fixed = almost_done.replace("(", "-");
// let negative_with_minus = half_fixed.replace(")", "");
// return negative_with_minus
// }
// }
// almost_done
// }
// Next, if ASCII (better be), check for accounting formatting
if almost_done.is_ascii() {
if almost_done.as_bytes()[0] == "(".as_bytes()[0] {
let half_fixed = almost_done.replace("(", "-");
let negative_with_minus = half_fixed.replace(")", "");
return negative_with_minus
}
}
almost_done
}
// fn sanitize_string_for_d128_parsing_full(field: &str) -> String {
fn sanitize_string_for_d128_parsing_full(field: &str) -> String {
// let mut near_done = "".to_string();
// // First, remove commas.
// let no_comma_string = field.replace(",", "");
// let almost_done = no_comma_string.replace(" ", "");
let mut near_done = "".to_string();
// First, remove commas.
let no_comma_string = field.replace(",", "");
let almost_done = no_comma_string.replace(" ", "");
// // Next, if ASCII (better be), check for accounting formating
// if almost_done.is_ascii() {
// if almost_done.as_bytes()[0] == "(".as_bytes()[0] {
// let half_fixed = almost_done.replace("(", "-");
// let negative_with_minus = half_fixed.replace(")", "");
// near_done = negative_with_minus;
// } else {
// near_done = almost_done;
// }
// } else {
// near_done = almost_done;
// }
// Next, if ASCII (better be), check for accounting formating
if almost_done.is_ascii() {
if almost_done.as_bytes()[0] == "(".as_bytes()[0] {
let half_fixed = almost_done.replace("(", "-");
let negative_with_minus = half_fixed.replace(")", "");
near_done = negative_with_minus;
} else {
near_done = almost_done;
}
} else {
near_done = almost_done;
}
// // Strip non-numeric and non-period characters
// let all_done: String = near_done.chars()
// .filter(|x|
// x.is_numeric() |
// (x == &(".".as_bytes()[0] as char)) |
// (x == &("-".as_bytes()[0] as char)))
// .collect();
// all_done
// }
// Strip non-numeric and non-period characters
let all_done: String = near_done.chars()
.filter(|x|
x.is_numeric() |
(x == &(".".as_bytes()[0] as char)) |
(x == &("-".as_bytes()[0] as char)))
.collect();
all_done
}
if let Some(incoming_ar) = incoming_ar {
let x = incoming_ar_num.unwrap();

View File

@ -1,20 +1,20 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use rust_decimal::Decimal;
use decimal::d128;
pub fn round_d128_generalized(to_round: &Decimal, places_past_decimal: u32) -> Decimal {
let rounded: Decimal = to_round.round_dp(places_past_decimal);
pub fn round_d128_generalized(to_round: &d128, places_past_decimal: d128) -> d128 {
let rounded: d128 = ((to_round * d128!(10).scaleb(places_past_decimal)).quantize(d128!(1e1))) / d128!(10).scaleb(places_past_decimal);
rounded//.reduce()
}
pub fn round_d128_1e2(to_round: &Decimal) -> Decimal {
let rounded: Decimal = to_round.round_dp(2);
pub fn round_d128_1e2(to_round: &d128) -> d128 {
let rounded: d128 = ((to_round * d128!(10).scaleb(d128!(2))).quantize(d128!(1e1))) / d128!(10).scaleb(d128!(2));
rounded//.reduce()
}
pub fn round_d128_1e8(to_round: &Decimal) -> Decimal {
let rounded: Decimal = to_round.round_dp(8);
pub fn round_d128_1e8(to_round: &d128) -> d128 {
let rounded: d128 = ((to_round * d128!(10).scaleb(d128!(8))).quantize(d128!(1e1))) / d128!(10).scaleb(d128!(8));
rounded//.reduce()
// Note: quantize() rounds the number to the right of decimal and keeps it, discarding the rest to the right (it appears). See test.
// In other words, it's off by one. If you raise 0.123456789 by 10e8, quantize to 1e1 (which is 10), it'll get 12345678.9, round off to 12345679, and end up .12345679

View File

@ -1,12 +1,11 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::collections::HashMap;
use std::error::Error;
use chrono::NaiveDate;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use crate::transaction::{Transaction, TxType, ActionRecord, Polarity};
use crate::account::{Account, RawAccount};
@ -67,8 +66,8 @@ pub(crate) fn add_cost_basis_to_movements(
mvmt.cost_basis.set(rounded_basis);
mvmt.cost_basis_lk.set(rounded_basis);
}
assert!(mvmt.cost_basis.get() <= dec!(0));
// assert!(mvmt.cost_basis_lk.get() <= dec!(0)); // Same as above assert.
assert!(mvmt.cost_basis.get() <= d128!(0));
// assert!(mvmt.cost_basis_lk.get() <= d128!(0)); // Same as above assert.
continue
}
@ -103,7 +102,7 @@ pub(crate) fn add_cost_basis_to_movements(
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r;
let txn_proceeds = txn.proceeds
.to_string()
.parse::<Decimal>()
.parse::<d128>()
.unwrap();
let unrounded_basis = txn_proceeds * ratio_of_amt_to_incoming_mvmts_in_a_r;
let rounded_basis = round_d128_1e2(&unrounded_basis);
@ -134,7 +133,7 @@ pub(crate) fn add_cost_basis_to_movements(
TxType::Flow => {
let txn_proceeds = txn.proceeds.to_string().parse::<Decimal>().unwrap();
let txn_proceeds = txn.proceeds.to_string().parse::<d128>().unwrap();
let mvmt_proceeds = round_d128_1e2(
&(txn_proceeds *
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r)
@ -145,8 +144,8 @@ pub(crate) fn add_cost_basis_to_movements(
}
}
}
assert!(mvmt.cost_basis.get() >= dec!(0));
// assert!(mvmt.cost_basis_lk.get() >= dec!(0)); // Same as above assert.
assert!(mvmt.cost_basis.get() >= d128!(0));
// assert!(mvmt.cost_basis_lk.get() >= d128!(0)); // Same as above assert.
continue
}
}
@ -163,7 +162,7 @@ pub(crate) fn add_cost_basis_to_movements(
ars: &HashMap<u32, ActionRecord>,
txns_map: &HashMap<u32, Transaction>,
acct_map: &HashMap<u16, Account>,
) -> Vec<Decimal> {
) -> Vec<d128> {
let txn = txns_map.get(&txn_num).unwrap();
let other_ar_borrowed = &ars.get(&txn.action_record_idx_vec[0]).unwrap();
@ -228,7 +227,7 @@ pub(crate) fn add_proceeds_to_movements(
}
let ratio = borrowed_mvmt.amount / ar.amount;
let proceeds_unrounded = txn.proceeds.to_string().parse::<Decimal>().unwrap() * ratio;
let proceeds_unrounded = txn.proceeds.to_string().parse::<d128>().unwrap() * ratio;
let proceeds_rounded = round_d128_1e2(&proceeds_unrounded);
mvmt.proceeds.set(proceeds_rounded);
@ -300,7 +299,7 @@ fn update_current_txn_for_prior_likekind_treatment(
txns_map: &HashMap<u32, Transaction>,
) -> Result<(), Box<dyn Error>> {
let mut sum_of_outgoing_lk_cost_basis_in_ar = dec!(0);
let mut sum_of_outgoing_lk_cost_basis_in_ar = d128!(0);
let txn = txns_map.get(&txn_num).unwrap();
for ar_num in txn.action_record_idx_vec.iter() {
@ -352,8 +351,8 @@ fn update_current_txn_for_prior_likekind_treatment(
}
TxType::Flow => {
if txn.action_record_idx_vec.len() == 2 {
mvmt.cost_basis_lk.set(dec!(0));
mvmt.proceeds_lk.set(dec!(0));
mvmt.cost_basis_lk.set(d128!(0));
mvmt.proceeds_lk.set(d128!(0));
}
// Do nothing for non-margin txns.
}
@ -399,7 +398,7 @@ fn perform_likekind_treatment_on_txn(
if txn.both_exch_ars_are_non_home_curr(ars, raw_acct_map, acct_map, home_currency)? {
let mut sum_of_outgoing_lk_cost_basis_in_ar = dec!(0);
let mut sum_of_outgoing_lk_cost_basis_in_ar = d128!(0);
for ar_num in txn.action_record_idx_vec.iter() {
@ -465,8 +464,8 @@ fn perform_likekind_treatment_on_txn(
Polarity::Incoming => {
// Reminder: May need extra logic here if margin exchange trades get cost_basis and proceeds
mvmt.cost_basis.set(dec!(0));
mvmt.proceeds.set(dec!(0));
mvmt.cost_basis.set(d128!(0));
mvmt.proceeds.set(d128!(0));
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
#![allow(dead_code)]

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2019, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
pub mod test;

View File

@ -1,13 +1,12 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::fs;
use std::collections::HashMap;
use std::collections::{HashMap};
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use crate::account::Account;
use crate::account::{Account};
use crate::transaction::{Transaction, ActionRecord};
use crate::decimal_utils::*;
@ -31,8 +30,8 @@ pub fn _run_tests(
&account_map
);
_test_quantize_from_incoming_multiple_lots_fn(dec!(20), dec!(200), dec!(50));
_test_quantize_from_incoming_multiple_lots_fn(dec!(1), dec!(6), dec!(1234567.1234567896));
_test_quantize_from_incoming_multiple_lots_fn(d128!(20), d128!(200), d128!(50));
_test_quantize_from_incoming_multiple_lots_fn(d128!(1), d128!(6), d128!(1234567.1234567896));
// test_dec_rounded("123456789.123456789");
// test_dec_rounded("123456.123456");
// test_dec_rounded("1234567891234.1234567891234");
@ -69,7 +68,7 @@ fn _compare_movements_across_implementations(
+ &ar.amount.to_string() + &"\n".to_string()
);
let mvmts = ar.get_mvmts_in_ar_in_lot_date_order(&account_map, &transactions_map);
let mut amts = dec!(0);
let mut amts = d128!(0);
for mvmt in mvmts {
amts += mvmt.amount;
line += &("Movement ".to_string() +
@ -79,7 +78,7 @@ fn _compare_movements_across_implementations(
&"\n".to_string());
}
line += &("Amount total: ".to_string() + &amts.to_string() + &"\n".to_string());
if amts - ar.amount != dec!(0) {
if amts - ar.amount != d128!(0) {
line += &("&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&".to_string());
println!("Movement amounts via get_mvmts_in_ar() different from actionRecord.amount. Aborting.");
use std::process::exit; exit(1)
@ -105,7 +104,7 @@ fn _compare_movements_across_implementations(
+ &"\n".to_string()
);
// let mvmts = ar.get_mvmts_in_ar(&account_map);
let mut amts = dec!(0);
let mut amts = d128!(0);
for mvmt in ar.movements.borrow().iter() {
amts += mvmt.amount;
line2 += &("Movement ".to_string() +
@ -115,7 +114,7 @@ fn _compare_movements_across_implementations(
&"\n".to_string());
}
line2 += &("Amount total: ".to_string() + &amts.to_string() + &"\n".to_string());
if amts - ar.amount != dec!(0) {
if amts - ar.amount != d128!(0) {
line2 += &("&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&".to_string());
println!("Movement amounts via ar.movements different from actionRecord.amount. Aborting.");
use std::process::exit; exit(1)
@ -145,9 +144,9 @@ pub fn _test_action_records_amts_vs_mvmt_amts(
account_map: &HashMap<u16, Account>,
) {
let mut mvmt_amt_acct_lot: Decimal = dec!(0);
let mut mvmt_amt_ar: Decimal = dec!(0);
let mut ar_amts: Decimal = dec!(0);
let mut mvmt_amt_acct_lot: d128 = d128!(0);
let mut mvmt_amt_ar: d128 = d128!(0);
let mut ar_amts: d128 = d128!(0);
for tx_num in 1..=transactions_map.len() {
@ -196,18 +195,18 @@ pub fn _test_action_records_amts_vs_mvmt_amts(
}
fn _test_quantize_from_incoming_multiple_lots_fn (
outgoing_mvmt_amt: Decimal,
outgoing_ar_amt: Decimal,
incoming_ar_amt: Decimal,
outgoing_mvmt_amt: d128,
outgoing_ar_amt: d128,
incoming_ar_amt: d128,
) {
let rounded_example = Decimal::new(1,8);
let rounded_example = d128::from(1).scaleb(d128::from(-8));
//
println!("Og mvmt amt: {:?}, Og ar amt: {:?}, Ic ar amt: {:?}", outgoing_mvmt_amt, outgoing_ar_amt, incoming_ar_amt);
let ratio_of_outgoing_to_total_ar = outgoing_mvmt_amt / outgoing_ar_amt; // Negative divided by negative is positive
println!("ratio_of_outgoing: {:.20}", ratio_of_outgoing_to_total_ar);
let tentative_incoming_amt = ratio_of_outgoing_to_total_ar * incoming_ar_amt;
println!("tentative_inc_amt: {:.20}", tentative_incoming_amt);
let corresponding_incoming_amt = tentative_incoming_amt.round_dp(8);
let corresponding_incoming_amt = tentative_incoming_amt.quantize(rounded_example);
println!("corresponding_inc_amt: {}", corresponding_incoming_amt);
}
@ -222,23 +221,23 @@ fn _test_quantize_from_incoming_multiple_lots_fn (
// corresponding_inc_amt: 205761.18724280
fn _test_dec_rounded(random_float_string: &str) {
let places_past_decimal = 8;
let amt = random_float_string.parse::<Decimal>().unwrap();
let places_past_decimal = d128!(8);
let amt = random_float_string.parse::<d128>().unwrap();
let amt2 = round_d128_generalized(&amt, places_past_decimal);
println!("Float into dec: {:?}; dec rounded to {}: {:?}", amt, places_past_decimal, amt2);
// Results of this test suggest that quantize() is off by one. round_dec_1e8() was adjusted accordingly.
println!("Float into d128: {:?}; d128 rounded to {}: {:?}", amt, places_past_decimal, amt2);
// Results of this test suggest that quantize() is off by one. round_d128_1e8() was adjusted accordingly.
}
fn _test_dec_rounded_1e8(random_float_string: &str) {
let amt = random_float_string.parse::<Decimal>().unwrap();
let amt = random_float_string.parse::<d128>().unwrap();
let amt2 = round_d128_1e8(&amt);
println!("Float into dec: {:?}; dec rounded to 8 places: {:?}", amt, amt2);
// Results of this test suggest that quantize() is off by one. round_dec_1e8() was adjusted accordingly.
println!("Float into d128: {:?}; d128 rounded to 8 places: {:?}", amt, amt2);
// Results of this test suggest that quantize() is off by one. round_d128_1e8() was adjusted accordingly.
}
fn _test_dec_rounded_1e2(random_float_string: &str) {
let amt = random_float_string.parse::<Decimal>().unwrap();
let amt = random_float_string.parse::<d128>().unwrap();
let amt2 = round_d128_1e2(&amt);
println!("String into dec: {:?}; dec rounded to 2 places: {:?}", amt, amt2);
// Results of this test suggest that quantize() is off by one. round_dec_1e8() was adjusted accordingly.
println!("String into d128: {:?}; d128 rounded to 2 places: {:?}", amt, amt2);
// Results of this test suggest that quantize() is off by one. round_d128_1e8() was adjusted accordingly.
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::rc::Rc;
@ -8,8 +8,7 @@ use std::fmt;
use std::collections::HashMap;
use std::error::Error;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use chrono::NaiveDate;
use serde_derive::{Serialize, Deserialize};
@ -298,7 +297,7 @@ impl Transaction {
let raw_acct = raw_accts.get(&acct.raw_key).unwrap();
let ticker = &raw_acct.ticker;
if amt > dec!(0.0) {
if amt > d128!(0.0) {
format!("Received {} {} valued at {:.2} {}.", amt, ticker,
self.proceeds.to_string().as_str().parse::<f32>()?, home_currency)
@ -318,7 +317,7 @@ impl Transaction {
#[derive(Clone, Debug)]
pub struct ActionRecord {
pub account_key: u16,
pub amount: Decimal,
pub amount: d128,
pub tx_key: u32,
pub self_ar_key: u32,
pub movements: RefCell<Vec<Rc<Movement>>>,
@ -327,13 +326,13 @@ pub struct ActionRecord {
impl ActionRecord {
pub fn direction(&self) -> Polarity {
if self.amount < dec!(0.0) { Polarity::Outgoing}
if self.amount < d128!(0.0) { Polarity::Outgoing}
else { Polarity::Incoming }
}
pub fn cost_basis_in_ar(&self) -> Decimal {
pub fn cost_basis_in_ar(&self) -> d128 {
let mut cb = dec!(0);
let mut cb = d128!(0);
for mvmt in self.movements.borrow().iter() {
cb += mvmt.cost_basis.get()
@ -374,7 +373,7 @@ impl ActionRecord {
let acct = acct_map.get(&self.account_key).unwrap();
let target = self.amount;
let mut measure = dec!(0);
let mut measure = d128!(0);
for lot in acct.list_of_lots.borrow().iter() {

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus;
// Copyright (c) 2017-2020, scoobybejesus;
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::fs::File;
@ -6,7 +6,7 @@ use std::collections::HashMap;
use std::path::PathBuf;
use std::error::Error;
use rust_decimal_macros::dec;
use decimal::d128;
use chrono::NaiveDate;
use crptls::transaction::{ActionRecord, Polarity, Transaction, TxType};
@ -47,7 +47,7 @@ pub fn _1_account_sums_to_csv(
let balance: String;
let tentative_balance = acct.get_sum_of_amts_in_lots();
if tentative_balance == dec!(0) {
if tentative_balance == d128!(0) {
balance = "0.00".to_string()
} else { balance = tentative_balance.to_string() }
@ -56,7 +56,7 @@ pub fn _1_account_sums_to_csv(
if raw_acct.is_margin { lk_cost_basis = "0.00".to_string() } else {
let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots();
if tentative_lk_cost_basis == dec!(0) {
if tentative_lk_cost_basis == d128!(0) {
lk_cost_basis = "0.00".to_string()
} else { lk_cost_basis = tentative_lk_cost_basis.to_string() }
}
@ -121,10 +121,10 @@ pub fn _2_account_sums_nonzero_to_csv(
let name = raw_acct.name.to_string();
let balance: String;
let mut balance_d128 = dec!(0);
let mut balance_d128 = d128!(0);
let tentative_balance = acct.get_sum_of_amts_in_lots();
if tentative_balance == dec!(0) {
if tentative_balance == d128!(0) {
balance = "0.00".to_string()
} else { balance_d128 += tentative_balance; balance = tentative_balance.to_string() }
@ -132,7 +132,7 @@ pub fn _2_account_sums_nonzero_to_csv(
if raw_acct.is_margin { lk_cost_basis = "0.00".to_string() } else {
let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots();
if tentative_lk_cost_basis == dec!(0) {
if tentative_lk_cost_basis == d128!(0) {
lk_cost_basis = "0.00".to_string()
} else { lk_cost_basis = tentative_lk_cost_basis.to_string() }
}
@ -142,7 +142,7 @@ pub fn _2_account_sums_nonzero_to_csv(
let nonzero_lots = acct.get_num_of_nonzero_lots();
if balance_d128 != dec!(0) {
if balance_d128 != d128!(0) {
row.push(name);
row.push(balance);
row.push(raw_acct.ticker.to_string());
@ -200,7 +200,7 @@ pub fn _3_account_sums_to_csv_with_orig_basis(
let balance: String;
let tentative_balance = acct.get_sum_of_amts_in_lots();
if tentative_balance == dec!(0) {
if tentative_balance == d128!(0) {
balance = "0.00".to_string()
} else { balance = tentative_balance.to_string() }
@ -217,11 +217,11 @@ pub fn _3_account_sums_to_csv_with_orig_basis(
let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots();
let tentative_orig_cost_basis = acct.get_sum_of_orig_basis_in_lots();
if tentative_lk_cost_basis == dec!(0) {
if tentative_lk_cost_basis == d128!(0) {
lk_cost_basis = "0.00".to_string()
} else { lk_cost_basis = tentative_lk_cost_basis.to_string() }
if tentative_orig_cost_basis == dec!(0) {
if tentative_orig_cost_basis == d128!(0) {
orig_cost_basis = "0.00".to_string()
} else { orig_cost_basis = tentative_orig_cost_basis.to_string() }
}
@ -312,7 +312,7 @@ pub fn _4_transaction_mvmt_detail_to_csv(
let tx_type = txn.transaction_type(&ars, &raw_acct_map, &acct_map)?;
let tx_type_string = mvmt.friendly_tx_type(&tx_type);
let memo = txn.user_memo.to_string();
let mut amount = dec!(0);
let mut amount = d128!(0);
amount += mvmt.amount; // To prevent printing -5E+1 instead of 50, for example
let ticker = raw_acct.ticker.to_string();
let term = mvmt.get_term(acct_map, ars, txns_map).to_string();
@ -323,10 +323,10 @@ pub fn _4_transaction_mvmt_detail_to_csv(
let expense = mvmt.get_expense(ars, &raw_acct_map, &acct_map, &txns_map)?;
if tx_type == TxType::Flow && amount > dec!(0) {
proceeds_lk = dec!(0);
cost_basis_lk = dec!(0);
gain_loss = dec!(0);
if tx_type == TxType::Flow && amount > d128!(0) {
proceeds_lk = d128!(0);
cost_basis_lk = d128!(0);
gain_loss = d128!(0);
}
let mut row: Vec<String> = Vec::with_capacity(total_columns);
@ -410,19 +410,19 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
let mut ticker: Option<String> = None;
let mut polarity: Option<Polarity> = None;
let mut amount_st = dec!(0);
let mut proceeds_st = dec!(0);
let mut cost_basis_st = dec!(0);
let mut amount_st = d128!(0);
let mut proceeds_st = d128!(0);
let mut cost_basis_st = d128!(0);
let mut income_st = dec!(0);
let mut expense_st = dec!(0);
let mut income_st = d128!(0);
let mut expense_st = d128!(0);
let mut amount_lt = dec!(0);
let mut proceeds_lt = dec!(0);
let mut cost_basis_lt = dec!(0);
let mut amount_lt = d128!(0);
let mut proceeds_lt = d128!(0);
let mut cost_basis_lt = d128!(0);
let mut income_lt = dec!(0);
let mut expense_lt = dec!(0);
let mut income_lt = d128!(0);
let mut expense_lt = d128!(0);
let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts(
&settings.home_currency,
@ -444,7 +444,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
if ticker.is_none() { ticker = Some(raw_acct.ticker.clone()) };
if polarity.is_none() {
polarity = if mvmt.amount > dec!(0) {
polarity = if mvmt.amount > d128!(0) {
Some(Polarity::Incoming)
} else { Some(Polarity::Outgoing)
};
@ -474,11 +474,11 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
&acct_map)? == TxType::Flow
) & (polarity == Some(Polarity::Incoming)) {
income_st = -proceeds_st; // Proceeds are negative for incoming txns
proceeds_st = dec!(0);
cost_basis_st = dec!(0);
proceeds_st = d128!(0);
cost_basis_st = d128!(0);
income_lt = -proceeds_lt; // Proceeds are negative for incoming txns
proceeds_lt = dec!(0);
cost_basis_lt = dec!(0);
proceeds_lt = d128!(0);
cost_basis_lt = d128!(0);
}
if (txn.transaction_type(
@ -620,7 +620,7 @@ pub fn _6_transaction_mvmt_detail_to_csv_w_orig(
let tx_type_string = mvmt.friendly_tx_type(&tx_type);
let user_memo = txn.user_memo.to_string();
let auto_memo = txn.get_auto_memo(ars, raw_acct_map,acct_map, &settings.home_currency)?;
let mut amount = dec!(0);
let mut amount = d128!(0);
amount += mvmt.amount; // To prevent printing -5E+1 instead of 50, for example
let ticker = raw_acct.ticker.to_string();
let term = mvmt.get_term(acct_map, ars, txns_map).to_string();
@ -633,13 +633,13 @@ pub fn _6_transaction_mvmt_detail_to_csv_w_orig(
let mut orig_cost = mvmt.cost_basis.get();
let mut orig_gain_loss = mvmt.get_orig_gain_or_loss();
if tx_type == TxType::Flow && amount > dec!(0) {
proceeds_lk = dec!(0);
cost_basis_lk = dec!(0);
gain_loss = dec!(0);
orig_proc = dec!(0);
orig_cost = dec!(0);
orig_gain_loss = dec!(0);
if tx_type == TxType::Flow && amount > d128!(0) {
proceeds_lk = d128!(0);
cost_basis_lk = d128!(0);
gain_loss = d128!(0);
orig_proc = d128!(0);
orig_cost = d128!(0);
orig_gain_loss = d128!(0);
}
let mut row: Vec<String> = Vec::with_capacity(total_columns);
@ -723,17 +723,17 @@ pub fn _7_gain_loss_8949_to_csv(
let mut ticker: Option<String> = None;
let mut polarity: Option<Polarity> = None;
let mut amount_st = dec!(0);
let mut proceeds_st = dec!(0);
let mut cost_basis_st = dec!(0);
let mut amount_st = d128!(0);
let mut proceeds_st = d128!(0);
let mut cost_basis_st = d128!(0);
let mut expense_st = dec!(0);
let mut expense_st = d128!(0);
let mut amount_lt = dec!(0);
let mut proceeds_lt = dec!(0);
let mut cost_basis_lt = dec!(0);
let mut amount_lt = d128!(0);
let mut proceeds_lt = d128!(0);
let mut cost_basis_lt = d128!(0);
let mut expense_lt = dec!(0);
let mut expense_lt = d128!(0);
let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts(
&settings.home_currency,
@ -757,7 +757,7 @@ pub fn _7_gain_loss_8949_to_csv(
if ticker.is_none() { ticker = Some(raw_acct.ticker.clone()) };
if polarity.is_none() {
polarity = if mvmt.amount > dec!(0) {
polarity = if mvmt.amount > d128!(0) {
Some(Polarity::Incoming)
} else { Some(Polarity::Outgoing)
};
@ -804,9 +804,9 @@ pub fn _7_gain_loss_8949_to_csv(
// The only incoming flow transaction to report would be margin profit, which is a dual-`action record` `transaction`
if txn.action_record_idx_vec.len() == 2 {
proceeds_st = -proceeds_st; // Proceeds are negative for incoming txns
cost_basis_st = dec!(0);
cost_basis_st = d128!(0);
proceeds_lt = -proceeds_lt; // Proceeds are negative for incoming txns
cost_basis_lt = dec!(0);
cost_basis_lt = d128!(0);
} else {
continue // Plain, old income isn't reported on form 8949
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::fs::OpenOptions;
@ -7,8 +7,7 @@ use std::path::PathBuf;
use std::error::Error;
use std::io::prelude::Write;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use crptls::transaction::{Transaction, ActionRecord, Polarity, TxType};
use crptls::account::{Account, RawAccount, Term};
@ -66,8 +65,8 @@ depending on the bookkeeping practices you employ.";
writeln!(file, "\n====================================================================================================\n")?;
let mut cost_basis_ic: Option<Decimal> = None;
let mut cost_basis_og: Option<Decimal> = None;
let mut cost_basis_ic: Option<d128> = None;
let mut cost_basis_og: Option<d128> = None;
let mut acct_string_ic = "".to_string();
let mut acct_string_og = "".to_string();
@ -102,16 +101,16 @@ depending on the bookkeeping practices you employ.";
let mut polarity: Option<Polarity> = None;
let mut amount_st = dec!(0);
let mut proceeds_st = dec!(0);
let mut cost_basis_st = dec!(0);
let mut amount_st = d128!(0);
let mut proceeds_st = d128!(0);
let mut cost_basis_st = d128!(0);
let mut amount_lt = dec!(0);
let mut proceeds_lt = dec!(0);
let mut cost_basis_lt = dec!(0);
let mut amount_lt = d128!(0);
let mut proceeds_lt = d128!(0);
let mut cost_basis_lt = d128!(0);
let mut income = dec!(0);
let mut expense = dec!(0);
let mut income = d128!(0);
let mut expense = d128!(0);
let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts(
&settings.home_currency,
@ -124,7 +123,7 @@ depending on the bookkeeping practices you employ.";
for mvmt in flow_or_outgoing_exchange_movements.iter() {
if polarity.is_none() {
polarity = if mvmt.amount > dec!(0) {
polarity = if mvmt.amount > d128!(0) {
Some(Polarity::Incoming)
} else { Some(Polarity::Outgoing)
};
@ -156,18 +155,18 @@ depending on the bookkeeping practices you employ.";
&acct_map)? == TxType::Flow
) & (polarity == Some(Polarity::Incoming)) {
proceeds_st = dec!(0);
cost_basis_st = dec!(0);
proceeds_st = d128!(0);
cost_basis_st = d128!(0);
proceeds_lt = dec!(0);
cost_basis_lt = dec!(0);
proceeds_lt = d128!(0);
cost_basis_lt = d128!(0);
}
let lt_gain_loss = proceeds_lt + cost_basis_lt;
let st_gain_loss = proceeds_st + cost_basis_st;
let mut debits = dec!(0);
let mut credits = dec!(0);
let mut debits = d128!(0);
let mut credits = d128!(0);
if let Some(cb) = cost_basis_ic {
debits += cb;
@ -191,9 +190,9 @@ depending on the bookkeeping practices you employ.";
)?;
}
if lt_gain_loss != dec!(0) {
if lt_gain_loss != d128!(0) {
if lt_gain_loss > dec!(0) {
if lt_gain_loss > d128!(0) {
credits += lt_gain_loss.abs();
let ltg_string = format!("Long-term gain disposing {}", amount_lt.abs());
writeln!(file, "{:50}{:5}{:>20}{:5}{:>20.2}",
@ -216,9 +215,9 @@ depending on the bookkeeping practices you employ.";
}
}
if st_gain_loss != dec!(0) {
if st_gain_loss != d128!(0) {
if st_gain_loss > dec!(0) {
if st_gain_loss > d128!(0) {
credits += st_gain_loss.abs();
let stg_string = format!("Short-term gain disposing {}", amount_st.abs());
writeln!(file, "{:50}{:5}{:>20}{:5}{:>20.2}",
@ -241,7 +240,7 @@ depending on the bookkeeping practices you employ.";
}
}
if income != dec!(0) {
if income != d128!(0) {
credits += income;
writeln!(file, "{:50}{:5}{:>20}{:5}{:>20.2}",
"Income",
@ -252,7 +251,7 @@ depending on the bookkeeping practices you employ.";
)?;
}
if expense != dec!(0) {
if expense != d128!(0) {
debits += expense.abs();
writeln!(file, "{:50}{:5}{:>20.2}{:5}{:>20}",
"Expense",
@ -286,7 +285,7 @@ depending on the bookkeeping practices you employ.";
auto_memo,
)?;
// if (debits - credits) != dec!(0) {
// if (debits - credits) != d128!(0) {
// println!("Rounding issue on transaction #{}", txn_num);
// }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::fs::OpenOptions;
@ -7,8 +7,7 @@ use std::path::PathBuf;
use std::error::Error;
use std::io::prelude::Write;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use decimal::d128;
use crptls::transaction::{Transaction, ActionRecord};
use crptls::account::{Account, RawAccount};
@ -130,14 +129,14 @@ Enable like-kind treatment: {}",
let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot();
let formatted_basis: String;
if lk_lot_basis == dec!(0) {
if lk_lot_basis == d128!(0) {
formatted_basis = "0.00".to_string()
} else { formatted_basis = lk_lot_basis.to_string() }
let movements_sum = lot.get_sum_of_amts_in_lot();
let formatted_sum: String;
if movements_sum == dec!(0) {
if movements_sum == d128!(0) {
formatted_sum = "0.00".to_string()
} else { formatted_sum = movements_sum.to_string() }
@ -201,15 +200,15 @@ Enable like-kind treatment: {}",
let lk_proceeds = mvmt.proceeds_lk.get();
let lk_cost_basis = mvmt.cost_basis_lk.get();
let gain_loss: Decimal;
let gain_loss: d128;
// if mvmt.amount > dec!(0) { // Can't have a gain on an incoming txn
// gain_loss = dec!(0)
// if mvmt.amount > d128!(0) { // Can't have a gain on an incoming txn
// gain_loss = d128!(0)
// } else
if raw_acct.is_home_currency(home_currency) { // Can't have a gain disposing home currency
gain_loss = dec!(0)
gain_loss = d128!(0)
// } else if tx_type == TxType::ToSelf { // Can't have a gain sending to yourself
// gain_loss = dec!(0)
// gain_loss = d128!(0)
} else {
gain_loss = lk_proceeds + lk_cost_basis;
}
@ -306,14 +305,14 @@ Enable like-kind treatment: {}",
let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot();
let formatted_basis: String;
if lk_lot_basis == dec!(0) {
if lk_lot_basis == d128!(0) {
formatted_basis = "0.00".to_string()
} else { formatted_basis = lk_lot_basis.to_string() }
let movements_sum = lot.get_sum_of_amts_in_lot();
let formatted_sum: String;
if movements_sum == dec!(0) {
if movements_sum == d128!(0) {
formatted_sum = "0.00".to_string()
} else { formatted_sum = movements_sum.to_string() }
@ -385,7 +384,7 @@ Enable like-kind treatment: {}",
let amt_in_acct = acct.get_sum_of_amts_in_lots();
if acct.list_of_lots.borrow().len() > 0 {
if amt_in_acct > dec!(0) {
if amt_in_acct > d128!(0) {
writeln!(file, "\n=====================================")?;
writeln!(file, "{} {}", raw_acct.name, raw_acct.ticker)?;
@ -405,13 +404,13 @@ Enable like-kind treatment: {}",
let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot();
let formatted_basis: String;
if lk_lot_basis == dec!(0) {
if lk_lot_basis == d128!(0) {
formatted_basis = "0.00".to_string()
} else { formatted_basis = lk_lot_basis.to_string() }
let movements_sum = lot.get_sum_of_amts_in_lot();
if acct.list_of_lots.borrow().len() > 0 && movements_sum > dec!(0) {
if acct.list_of_lots.borrow().len() > 0 && movements_sum > d128!(0) {
writeln!(file, " Lot {:>3} created {} w/ basis date {} • Σ: {:>12}, and cost basis of {:>10.2}",
(lot_idx+1),

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
pub mod export_all;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
// #![allow(dead_code)]

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
// TODO: cite source?

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
pub mod print_menu_tui;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::io;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::io;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::path::PathBuf;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::path::PathBuf;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017-2023, scoobybejesus
// Copyright (c) 2017-2020, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;