bullet_exchange_interface/decimals/
ops.rs1use std::str::FromStr;
2
3use rust_decimal::{Decimal, MathematicalOps};
4
5use crate::error::{ArithmeticError, ArithmeticOperation, ConfigError};
6
7pub trait TryDecimalOps {
8 fn try_from_str(value: &str) -> Result<Self, ConfigError>
9 where
10 Self: Sized;
11 fn try_add(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError>
12 where
13 Self: Sized;
14 fn try_sub(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError>
15 where
16 Self: Sized;
17 fn try_mul(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError>
18 where
19 Self: Sized;
20 fn try_div(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError>
21 where
22 Self: Sized;
23 fn try_exp(self) -> Result<Self, ArithmeticError>
24 where
25 Self: Sized;
26}
27
28impl TryDecimalOps for Decimal {
29 #[inline]
30 fn try_from_str(value: &str) -> Result<Self, ConfigError> {
31 Decimal::from_str(value).map_err(|_| ConfigError::FailedToParseInput {
32 input: value.to_string(),
33 reason: format!(
34 "Provided string value for {value} cannot be converted to the underlying type (Decimal)",
35 )
36 })
37 }
38
39 #[inline]
40 fn try_add(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError> {
41 let v = v.into();
42 self.checked_add(v).ok_or(ArithmeticError::DecimalFailed {
43 operation: ArithmeticOperation::Addition,
44 left: self,
45 right: v,
46 })
47 }
48
49 #[inline]
50 fn try_sub(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError> {
51 let v = v.into();
52 self.checked_sub(v).ok_or(ArithmeticError::DecimalFailed {
53 operation: ArithmeticOperation::Subtraction,
54 left: self,
55 right: v,
56 })
57 }
58
59 #[inline]
60 fn try_mul(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError> {
61 let v = v.into();
62 self.checked_mul(v).ok_or(ArithmeticError::DecimalFailed {
63 operation: ArithmeticOperation::Multiplication,
64 left: self,
65 right: v,
66 })
67 }
68
69 #[inline]
70 fn try_div(self, v: impl Into<Decimal>) -> Result<Self, ArithmeticError> {
71 let v = v.into();
72 self.checked_div(v).ok_or(ArithmeticError::DecimalFailed {
73 operation: ArithmeticOperation::Division,
74 left: self,
75 right: v,
76 })
77 }
78
79 #[inline]
80 fn try_exp(self) -> Result<Self, ArithmeticError> {
81 self.checked_exp().ok_or(ArithmeticError::DecimalFailed {
82 operation: ArithmeticOperation::Exponentiation,
83 left: self,
84 right: Decimal::ZERO,
85 })
86 }
87}