teaql_tool_std/
decimal.rs1use rust_decimal::Decimal;
2use rust_decimal::RoundingStrategy;
3use std::str::FromStr;
4use teaql_tool_core::{MustPurpose, Result, TeaQLToolError};
5
6pub struct DecimalTool;
7
8impl DecimalTool {
9 pub fn new() -> Self {
10 Self
11 }
12
13 pub fn of(&self, s: &str) -> Result<MustPurpose<Decimal>> {
14 Decimal::from_str(s)
15 .map(MustPurpose::new)
16 .map_err(|e| TeaQLToolError::ParseError(e.to_string()))
17 }
18
19 pub fn zero(&self) -> MustPurpose<Decimal> {
20 MustPurpose::new(Decimal::ZERO)
21 }
22
23 pub fn one(&self) -> MustPurpose<Decimal> {
24 MustPurpose::new(Decimal::ONE)
25 }
26
27 pub fn add(&self, a: Decimal, b: Decimal) -> MustPurpose<Decimal> {
28 MustPurpose::new(a + b)
29 }
30
31 pub fn sub(&self, a: Decimal, b: Decimal) -> MustPurpose<Decimal> {
32 MustPurpose::new(a - b)
33 }
34
35 pub fn mul(&self, a: Decimal, b: Decimal) -> MustPurpose<Decimal> {
36 MustPurpose::new(a * b)
37 }
38
39 pub fn div(&self, a: Decimal, b: Decimal) -> Result<MustPurpose<Decimal>> {
40 if b.is_zero() {
41 Err(TeaQLToolError::InvalidArgument(
42 "Division by zero".to_string(),
43 ))
44 } else {
45 Ok(MustPurpose::new(a / b))
46 }
47 }
48
49 pub fn round(&self, a: Decimal, dp: u32) -> MustPurpose<Decimal> {
50 MustPurpose::new(a.round_dp_with_strategy(dp, RoundingStrategy::MidpointNearestEven))
51 }
52
53 pub fn ceil(&self, a: Decimal) -> MustPurpose<Decimal> {
54 MustPurpose::new(a.ceil())
55 }
56
57 pub fn floor(&self, a: Decimal) -> MustPurpose<Decimal> {
58 MustPurpose::new(a.floor())
59 }
60
61 pub fn abs(&self, a: Decimal) -> MustPurpose<Decimal> {
62 MustPurpose::new(a.abs())
63 }
64
65 pub fn min(&self, a: Decimal, b: Decimal) -> MustPurpose<Decimal> {
66 MustPurpose::new(a.min(b))
67 }
68
69 pub fn max(&self, a: Decimal, b: Decimal) -> MustPurpose<Decimal> {
70 MustPurpose::new(a.max(b))
71 }
72
73 pub fn percent(&self, amount: Decimal, pct: Decimal) -> MustPurpose<Decimal> {
74 MustPurpose::new((amount * pct) / Decimal::from(100))
75 }
76
77 pub fn ratio(&self, part: Decimal, total: Decimal) -> Result<MustPurpose<Decimal>> {
78 self.div(part, total)
79 }
80}
81
82impl Default for DecimalTool {
83 fn default() -> Self {
84 Self::new()
85 }
86}