1use core::ops;
27
28use NumOpResult as R;
29
30use crate::{Amount, FeeRate, NumOpResult, Weight};
31
32crate::internal_macros::impl_op_for_references! {
33 impl ops::Mul<FeeRate> for Weight {
34 type Output = NumOpResult<Amount>;
35 fn mul(self, rhs: FeeRate) -> Self::Output { rhs.mul_by_weight(self) }
36 }
37 impl ops::Mul<FeeRate> for NumOpResult<Weight> {
38 type Output = NumOpResult<Amount>;
39 fn mul(self, rhs: FeeRate) -> Self::Output {
40 match self {
41 R::Valid(lhs) => lhs * rhs,
42 R::Error(e) => NumOpResult::Error(e),
43 }
44 }
45 }
46 impl ops::Mul<NumOpResult<FeeRate>> for Weight {
47 type Output = NumOpResult<Amount>;
48 fn mul(self, rhs: NumOpResult<FeeRate>) -> Self::Output {
49 match rhs {
50 R::Valid(fee_rate) => self * fee_rate,
51 R::Error(e) => NumOpResult::Error(e),
52 }
53 }
54 }
55 impl ops::Mul<NumOpResult<FeeRate>> for NumOpResult<Weight> {
56 type Output = NumOpResult<Amount>;
57 fn mul(self, rhs: NumOpResult<FeeRate>) -> Self::Output {
58 match self {
59 R::Valid(lhs) => { match rhs {
60 R::Valid(fee_rate) => lhs * fee_rate,
61 R::Error(e) => NumOpResult::Error(e),
62 }}
63 R::Error(e) => NumOpResult::Error(e),
64 }
65 }
66 }
67
68 impl ops::Mul<Weight> for FeeRate {
69 type Output = NumOpResult<Amount>;
70 fn mul(self, rhs: Weight) -> Self::Output { self.mul_by_weight(rhs) }
71 }
72 impl ops::Mul<Weight> for NumOpResult<FeeRate> {
73 type Output = NumOpResult<Amount>;
74 fn mul(self, rhs: Weight) -> Self::Output {
75 match self {
76 R::Valid(lhs) => lhs * rhs,
77 R::Error(e) => NumOpResult::Error(e),
78 }
79 }
80 }
81 impl ops::Mul<NumOpResult<Weight>> for FeeRate {
82 type Output = NumOpResult<Amount>;
83 fn mul(self, rhs: NumOpResult<Weight>) -> Self::Output {
84 match rhs {
85 R::Valid(weight) => self * weight,
86 R::Error(e) => NumOpResult::Error(e),
87 }
88 }
89 }
90 impl ops::Mul<NumOpResult<Weight>> for NumOpResult<FeeRate> {
91 type Output = NumOpResult<Amount>;
92 fn mul(self, rhs: NumOpResult<Weight>) -> Self::Output {
93 match self {
94 R::Valid(lhs) => { match rhs {
95 R::Valid(weight) => lhs * weight,
96 R::Error(e) => NumOpResult::Error(e),
97 }}
98 R::Error(e) => NumOpResult::Error(e),
99 }
100 }
101 }
102
103 impl ops::Div<Weight> for Amount {
104 type Output = NumOpResult<FeeRate>;
105
106 fn div(self, rhs: Weight) -> Self::Output {
107 self.div_by_weight_floor(rhs)
108 }
109 }
110 impl ops::Div<Weight> for NumOpResult<Amount> {
111 type Output = NumOpResult<FeeRate>;
112
113 fn div(self, rhs: Weight) -> Self::Output {
114 match self {
115 R::Valid(lhs) => lhs / rhs,
116 R::Error(e) => NumOpResult::Error(e),
117 }
118 }
119 }
120 impl ops::Div<NumOpResult<Weight>> for Amount {
121 type Output = NumOpResult<FeeRate>;
122
123 fn div(self, rhs: NumOpResult<Weight>) -> Self::Output {
124 match rhs {
125 R::Valid(weight) => self / weight,
126 R::Error(e) => NumOpResult::Error(e),
127 }
128 }
129 }
130 impl ops::Div<NumOpResult<Weight>> for NumOpResult<Amount> {
131 type Output = NumOpResult<FeeRate>;
132
133 fn div(self, rhs: NumOpResult<Weight>) -> Self::Output {
134 match self {
135 R::Valid(lhs) => { match rhs {
136 R::Valid(weight) => lhs / weight,
137 R::Error(e) => NumOpResult::Error(e),
138 }}
139 R::Error(e) => NumOpResult::Error(e),
140 }
141 }
142 }
143
144 impl ops::Div<FeeRate> for Amount {
145 type Output = NumOpResult<Weight>;
146
147 fn div(self, rhs: FeeRate) -> Self::Output {
148 self.div_by_fee_rate_floor(rhs)
149 }
150 }
151 impl ops::Div<FeeRate> for NumOpResult<Amount> {
152 type Output = NumOpResult<Weight>;
153
154 fn div(self, rhs: FeeRate) -> Self::Output {
155 match self {
156 R::Valid(lhs) => lhs / rhs,
157 R::Error(e) => NumOpResult::Error(e),
158 }
159 }
160 }
161 impl ops::Div<NumOpResult<FeeRate>> for Amount {
162 type Output = NumOpResult<Weight>;
163
164 fn div(self, rhs: NumOpResult<FeeRate>) -> Self::Output {
165 match rhs {
166 R::Valid(fee_rate) => self / fee_rate,
167 R::Error(e) => NumOpResult::Error(e),
168 }
169 }
170 }
171 impl ops::Div<NumOpResult<FeeRate>> for NumOpResult<Amount> {
172 type Output = NumOpResult<Weight>;
173
174 fn div(self, rhs: NumOpResult<FeeRate>) -> Self::Output {
175 match self {
176 R::Valid(lhs) => { match rhs {
177 R::Valid(fee_rate) => lhs / fee_rate,
178 R::Error(e) => NumOpResult::Error(e),
179 }}
180 R::Error(e) => NumOpResult::Error(e),
181 }
182 }
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[test]
191 fn fee_rate_div_by_weight() {
192 let fee_rate = (Amount::from_sat_u32(329) / Weight::from_wu(381)).unwrap();
193 assert_eq!(fee_rate, FeeRate::from_sat_per_kwu(863));
194 }
195
196 #[test]
197 fn fee_wu() {
198 let fee_rate = FeeRate::from_sat_per_vb(2);
199 let weight = Weight::from_vb(3).unwrap();
200 assert_eq!(fee_rate.to_fee(weight), Amount::from_sat_u32(6));
201 }
202
203 #[test]
204 fn weight_mul() {
205 let weight = Weight::from_vb(10).unwrap();
206 let fee: Amount =
207 FeeRate::from_sat_per_vb(10).mul_by_weight(weight).expect("expected Amount");
208 assert_eq!(Amount::from_sat_u32(100), fee);
209
210 let fee = FeeRate::from_sat_per_kwu(10).mul_by_weight(Weight::MAX);
211 assert!(fee.is_error());
212
213 let weight = Weight::from_vb(3).unwrap();
214 let fee_rate = FeeRate::from_sat_per_vb(3);
215 let fee = fee_rate.mul_by_weight(weight).unwrap();
216 assert_eq!(Amount::from_sat_u32(9), fee);
217
218 let weight = Weight::from_wu(381);
219 let fee_rate = FeeRate::from_sat_per_kwu(864);
220 let fee = weight.mul_by_fee_rate(fee_rate).unwrap();
221 assert_eq!(fee, Amount::from_sat_u32(330));
224 }
225
226 #[test]
227 #[allow(clippy::op_ref)]
228 fn multiply() {
229 let two = FeeRate::from_sat_per_vb(2);
230 let three = Weight::from_vb(3).unwrap();
231 let six = Amount::from_sat_u32(6);
232
233 assert_eq!(two * three, six.into());
234
235 assert_eq!(&two * three, six.into());
237 assert_eq!(two * &three, six.into());
238 assert_eq!(&two * &three, six.into());
239 }
240
241 #[test]
242 #[allow(clippy::op_ref)]
243 fn amount_div_by_fee_rate() {
244 let amount = Amount::from_sat_u32(1000);
246 let fee_rate = FeeRate::from_sat_per_kwu(2);
247 let weight = amount / fee_rate;
248 assert_eq!(weight.unwrap(), Weight::from_wu(500_000));
249
250 let weight_ref = (&amount / fee_rate).unwrap();
252 assert_eq!(weight_ref, Weight::from_wu(500_000));
253 let weight_ref2 = (amount / &fee_rate).unwrap();
254 assert_eq!(weight_ref2, Weight::from_wu(500_000));
255 let weight_ref3 = (&amount / &fee_rate).unwrap();
256 assert_eq!(weight_ref3, Weight::from_wu(500_000));
257
258 let amount = Amount::from_sat_u32(1000);
260 let fee_rate = FeeRate::from_sat_per_kwu(3);
261 let weight = amount / fee_rate;
262 assert_eq!(weight.unwrap(), Weight::from_wu(333_333));
266
267 let ceil_weight = amount.div_by_fee_rate_ceil(fee_rate).unwrap();
269 assert_eq!(ceil_weight, Weight::from_wu(333_334));
270
271 let zero_rate = FeeRate::from_sat_per_kwu(0);
273 assert!(amount.div_by_fee_rate_floor(zero_rate).is_error());
274 assert!(amount.div_by_fee_rate_ceil(zero_rate).is_error());
275 }
276}