1use crate::{
2 abi::{TypeAbi, TypeAbiFrom, TypeName},
3 api::{
4 const_handles, use_raw_handle, BigFloatApiImpl, BigIntApiImpl, HandleConstraints,
5 ManagedBufferApiImpl, ManagedTypeApi,
6 },
7 err_msg,
8 formatter::{FormatBuffer, FormatByteReceiver, SCDisplay},
9 typenum::{Unsigned, U4, U8},
10 types::{
11 managed_vec_item_read_from_payload_index, managed_vec_item_save_to_payload_index, BigFloat,
12 BigInt, BigUint, ManagedVecItem, ManagedVecItemPayloadBuffer, ManagedVecRef, Sign,
13 },
14};
15
16use alloc::string::ToString;
17use multiversx_sc_codec::{
18 DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput,
19 NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput,
20};
21
22use core::{cmp::Ordering, ops::Deref};
23
24use super::{
25 decimals::{ConstDecimals, Decimals, NumDecimals},
26 ManagedDecimal,
27};
28use super::{ManagedBufferCachedBuilder, ManagedRef};
29
30#[derive(Clone)]
34pub struct ManagedDecimalSigned<M: ManagedTypeApi, D: Decimals> {
35 pub(crate) data: BigInt<M>,
36 pub(crate) decimals: D,
37}
38
39impl<M: ManagedTypeApi, D: Decimals> ManagedDecimalSigned<M, D> {
40 pub fn trunc(&self) -> BigInt<M> {
41 &self.data / self.decimals.scaling_factor().deref()
42 }
43
44 pub fn into_raw_units(&self) -> &BigInt<M> {
45 &self.data
46 }
47
48 pub fn from_raw_units(data: BigInt<M>, decimals: D) -> Self {
49 ManagedDecimalSigned { data, decimals }
50 }
51
52 pub fn scale(&self) -> usize {
53 self.decimals.num_decimals()
54 }
55
56 pub fn scaling_factor(&self) -> ManagedRef<'static, M, BigUint<M>> {
57 self.decimals.scaling_factor()
58 }
59
60 pub(crate) fn rescale_data(&self, scale_to_num_decimals: NumDecimals) -> BigInt<M> {
61 let from_num_decimals = self.decimals.num_decimals();
62
63 match from_num_decimals.cmp(&scale_to_num_decimals) {
64 Ordering::Less => {
65 let delta_decimals = scale_to_num_decimals - from_num_decimals;
66 let scaling_factor: &BigUint<M> = &delta_decimals.scaling_factor();
67 &self.data * &scaling_factor.value
68 }
69 Ordering::Equal => self.data.clone(),
70 Ordering::Greater => {
71 let delta_decimals = from_num_decimals - scale_to_num_decimals;
72 let scaling_factor: &BigUint<M> = &delta_decimals.scaling_factor();
73 &self.data / &scaling_factor.value
74 }
75 }
76 }
77
78 pub fn rescale<T: Decimals>(&self, scale_to: T) -> ManagedDecimalSigned<M, T> {
79 let scale_to_num_decimals = scale_to.num_decimals();
80 ManagedDecimalSigned::from_raw_units(self.rescale_data(scale_to_num_decimals), scale_to)
81 }
82
83 pub fn into_unsigned_or_fail(self) -> ManagedDecimal<M, D> {
84 ManagedDecimal {
85 data: self
86 .data
87 .into_big_uint()
88 .unwrap_or_sc_panic(err_msg::UNSIGNED_NEGATIVE),
89 decimals: self.decimals,
90 }
91 }
92
93 pub fn sign(&self) -> Sign {
94 self.data.sign()
95 }
96}
97
98impl<M: ManagedTypeApi, DECIMALS: Unsigned> ManagedDecimalSigned<M, ConstDecimals<DECIMALS>> {
99 pub fn const_decimals_from_raw(data: BigInt<M>) -> Self {
100 ManagedDecimalSigned {
101 data,
102 decimals: ConstDecimals::new(),
103 }
104 }
105
106 pub fn into_var_decimals(self) -> ManagedDecimalSigned<M, NumDecimals> {
108 ManagedDecimalSigned {
109 data: self.data,
110 decimals: DECIMALS::to_usize(),
111 }
112 }
113}
114
115impl<M: ManagedTypeApi, DECIMALS: Unsigned> From<BigInt<M>>
116 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
117{
118 fn from(mut value: BigInt<M>) -> Self {
119 let decimals = ConstDecimals::new();
120 value *= decimals.scaling_factor().as_big_int();
121 ManagedDecimalSigned {
122 data: value,
123 decimals,
124 }
125 }
126}
127
128impl<M: ManagedTypeApi, DECIMALS: Unsigned> From<i64>
129 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
130{
131 fn from(value: i64) -> Self {
132 Self::from(BigInt::from(value))
133 }
134}
135
136impl<M: ManagedTypeApi, D: Decimals> ManagedDecimalSigned<M, D> {
137 pub fn to_big_float(&self) -> BigFloat<M> {
138 let result = BigFloat::from_big_int(&self.data);
139 let temp_handle: M::BigFloatHandle = use_raw_handle(const_handles::BIG_FLOAT_TEMPORARY);
140 let denominator = self.decimals.scaling_factor::<M>();
141 M::managed_type_impl().bf_set_bi(temp_handle.clone(), denominator.handle);
142 M::managed_type_impl().bf_div(result.handle.clone(), result.handle.clone(), temp_handle);
143 result
144 }
145
146 pub fn from_big_float<T: Decimals>(
147 big_float: &BigFloat<M>,
148 num_decimals: T,
149 ) -> ManagedDecimalSigned<M, T> {
150 let scaling_factor: &BigUint<M> = &num_decimals.scaling_factor();
151
152 let scaled = &BigFloat::from(scaling_factor) * big_float;
153 let fixed_big_int = scaled.trunc();
154
155 ManagedDecimalSigned::from_raw_units(fixed_big_int, num_decimals)
156 }
157}
158
159impl<M: ManagedTypeApi, DECIMALS: Unsigned> From<&BigFloat<M>>
160 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
161{
162 fn from(value: &BigFloat<M>) -> Self {
163 Self::from_big_float(value, ConstDecimals::new())
164 }
165}
166
167impl<M: ManagedTypeApi, DECIMALS: Unsigned> From<BigFloat<M>>
168 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
169{
170 #[inline]
171 fn from(value: BigFloat<M>) -> Self {
172 Self::from(&value)
173 }
174}
175
176impl<M: ManagedTypeApi, DECIMALS: Unsigned> From<f64>
177 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
178{
179 fn from(x: f64) -> Self {
180 Self::from(BigFloat::from(x))
181 }
182}
183
184impl<M: ManagedTypeApi, DECIMALS: Unsigned> From<f32>
185 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
186{
187 fn from(x: f32) -> Self {
188 Self::from(x as f64)
189 }
190}
191
192impl<M: ManagedTypeApi> ManagedVecItem for ManagedDecimalSigned<M, NumDecimals> {
193 type PAYLOAD = ManagedVecItemPayloadBuffer<U8>; const SKIPS_RESERIALIZATION: bool = false;
196
197 type Ref<'a> = ManagedVecRef<'a, Self>;
198
199 fn read_from_payload(payload: &Self::PAYLOAD) -> Self {
200 let mut index = 0;
201 unsafe {
202 Self {
203 data: managed_vec_item_read_from_payload_index(payload, &mut index),
204 decimals: managed_vec_item_read_from_payload_index(payload, &mut index),
205 }
206 }
207 }
208
209 unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> {
210 ManagedVecRef::new(Self::read_from_payload(payload))
211 }
212
213 fn save_to_payload(self, payload: &mut Self::PAYLOAD) {
214 let mut index = 0;
215 unsafe {
216 managed_vec_item_save_to_payload_index(self.data, payload, &mut index);
217 managed_vec_item_save_to_payload_index(self.decimals, payload, &mut index);
218 }
219 }
220}
221
222impl<M: ManagedTypeApi, DECIMALS: Unsigned> ManagedVecItem
223 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
224{
225 type PAYLOAD = ManagedVecItemPayloadBuffer<U4>; const SKIPS_RESERIALIZATION: bool = false;
228
229 type Ref<'a> = ManagedVecRef<'a, Self>;
230
231 fn read_from_payload(payload: &Self::PAYLOAD) -> Self {
232 Self::const_decimals_from_raw(BigInt::read_from_payload(payload))
233 }
234
235 unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> {
236 ManagedVecRef::new(Self::read_from_payload(payload))
237 }
238
239 fn save_to_payload(self, payload: &mut Self::PAYLOAD) {
240 self.data.save_to_payload(payload);
241 }
242}
243
244impl<M: ManagedTypeApi, DECIMALS: Unsigned> TopEncode
245 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
246{
247 #[inline]
248 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
249 where
250 O: TopEncodeOutput,
251 H: EncodeErrorHandler,
252 {
253 self.data.top_encode_or_handle_err(output, h)
254 }
255}
256
257impl<M: ManagedTypeApi, DECIMALS: Unsigned> TopDecode
258 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
259{
260 fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
261 where
262 I: TopDecodeInput,
263 H: DecodeErrorHandler,
264 {
265 Ok(ManagedDecimalSigned::const_decimals_from_raw(
266 BigInt::top_decode_or_handle_err(input, h)?,
267 ))
268 }
269}
270
271impl<M: ManagedTypeApi, DECIMALS: Unsigned> NestedEncode
272 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
273{
274 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
275 where
276 O: NestedEncodeOutput,
277 H: EncodeErrorHandler,
278 {
279 NestedEncode::dep_encode_or_handle_err(&self.data, dest, h)?;
280
281 Result::Ok(())
282 }
283}
284
285impl<M: ManagedTypeApi, DECIMALS: Unsigned> NestedDecode
286 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
287{
288 fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
289 where
290 I: NestedDecodeInput,
291 H: DecodeErrorHandler,
292 {
293 Result::Ok(ManagedDecimalSigned::const_decimals_from_raw(
294 <BigInt<M> as NestedDecode>::dep_decode_or_handle_err(input, h)?,
295 ))
296 }
297}
298
299impl<M: ManagedTypeApi> NestedEncode for ManagedDecimalSigned<M, NumDecimals> {
300 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
301 where
302 O: NestedEncodeOutput,
303 H: EncodeErrorHandler,
304 {
305 NestedEncode::dep_encode_or_handle_err(&self.data, dest, h)?;
306 NestedEncode::dep_encode_or_handle_err(&self.decimals, dest, h)?;
307
308 Result::Ok(())
309 }
310}
311
312impl<M: ManagedTypeApi> TopEncode for ManagedDecimalSigned<M, NumDecimals> {
313 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
314 where
315 O: TopEncodeOutput,
316 H: EncodeErrorHandler,
317 {
318 let mut buffer = output.start_nested_encode();
319 let dest = &mut buffer;
320 NestedEncode::dep_encode_or_handle_err(&self.data, dest, h)?;
321 NestedEncode::dep_encode_or_handle_err(&self.decimals, dest, h)?;
322
323 output.finalize_nested_encode(buffer);
324 Result::Ok(())
325 }
326}
327
328impl<M: ManagedTypeApi> NestedDecode for ManagedDecimalSigned<M, NumDecimals> {
329 fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
330 where
331 I: NestedDecodeInput,
332 H: DecodeErrorHandler,
333 {
334 Result::Ok(ManagedDecimalSigned::from_raw_units(
335 <BigInt<M> as NestedDecode>::dep_decode_or_handle_err(input, h)?,
336 <NumDecimals as NestedDecode>::dep_decode_or_handle_err(input, h)?,
337 ))
338 }
339}
340
341impl<M: ManagedTypeApi> TopDecode for ManagedDecimalSigned<M, NumDecimals> {
342 fn top_decode_or_handle_err<I, H>(top_input: I, h: H) -> Result<Self, H::HandledErr>
343 where
344 I: TopDecodeInput,
345 H: DecodeErrorHandler,
346 {
347 let mut nested_buffer = top_input.into_nested_buffer();
348 let result = ManagedDecimalSigned::from_raw_units(
349 <BigInt<M> as NestedDecode>::dep_decode_or_handle_err(&mut nested_buffer, h)?,
350 <NumDecimals as NestedDecode>::dep_decode_or_handle_err(&mut nested_buffer, h)?,
351 );
352 if !NestedDecodeInput::is_depleted(&nested_buffer) {
353 return Result::Err(h.handle_error(DecodeError::INPUT_TOO_LONG));
354 }
355 Result::Ok(result)
356 }
357}
358
359impl<M: ManagedTypeApi> TypeAbiFrom<Self> for ManagedDecimalSigned<M, NumDecimals> {}
360
361impl<M: ManagedTypeApi> TypeAbi for ManagedDecimalSigned<M, NumDecimals> {
362 type Unmanaged = Self;
363
364 fn type_name() -> TypeName {
365 TypeName::from("ManagedDecimalSigned<usize>")
366 }
367
368 fn is_variadic() -> bool {
369 false
370 }
371}
372
373impl<M: ManagedTypeApi, DECIMALS: Unsigned> TypeAbiFrom<Self>
374 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
375{
376}
377
378impl<M: ManagedTypeApi, DECIMALS: Unsigned> TypeAbi
379 for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
380{
381 type Unmanaged = Self;
382
383 fn type_name() -> TypeName {
384 TypeName::from(alloc::format!(
385 "ManagedDecimalSigned<{}>",
386 DECIMALS::to_usize()
387 ))
388 }
389
390 fn type_name_rust() -> TypeName {
391 TypeName::from(alloc::format!(
392 "ManagedDecimalSigned<$API, ConstDecimals<{}>>",
393 DECIMALS::to_usize()
394 ))
395 }
396
397 fn is_variadic() -> bool {
398 false
399 }
400}
401
402pub(super) fn managed_decimal_fmt<M: ManagedTypeApi, F: FormatByteReceiver>(
403 value: &BigInt<M>,
404 num_dec: NumDecimals,
405 f: &mut F,
406) {
407 let full_str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1);
408 M::managed_type_impl().bi_to_string(value.handle.clone(), full_str_handle.clone());
409 let len = M::managed_type_impl().mb_len(full_str_handle.clone());
410
411 if len > num_dec {
412 let temp_str_handle: M::ManagedBufferHandle =
413 use_raw_handle(const_handles::MBUF_TEMPORARY_2);
414 let cast_handle = temp_str_handle.clone().cast_or_signal_error::<M, _>();
415 let temp_str_ref = unsafe { ManagedRef::wrap_handle(cast_handle) };
416 let _ = M::managed_type_impl().mb_copy_slice(
417 full_str_handle.clone(),
418 0,
419 len - num_dec,
420 temp_str_handle.clone(),
421 );
422 f.append_managed_buffer(&temp_str_ref);
423 f.append_bytes(b".");
424 let _ = M::managed_type_impl().mb_copy_slice(
425 full_str_handle.clone(),
426 len - num_dec,
427 num_dec,
428 temp_str_handle.clone(),
429 );
430 f.append_managed_buffer(&temp_str_ref);
431 } else {
432 f.append_bytes(b"0.");
433 for _ in len..num_dec {
434 f.append_bytes(b"0");
435 }
436 let cast_handle = full_str_handle.clone().cast_or_signal_error::<M, _>();
437 let full_str_ref = unsafe { ManagedRef::wrap_handle(cast_handle) };
438 f.append_managed_buffer(&full_str_ref);
439 }
440}
441
442impl<M: ManagedTypeApi, D: Decimals> SCDisplay for ManagedDecimalSigned<M, D> {
443 fn fmt<F: FormatByteReceiver>(&self, f: &mut F) {
444 managed_decimal_fmt(&self.data, self.decimals.num_decimals(), f);
445 }
446}
447
448impl<M: ManagedTypeApi, D: Decimals> core::fmt::Display for ManagedDecimalSigned<M, D> {
449 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
450 let mut result = ManagedBufferCachedBuilder::<M>::new_from_slice(&[]);
451 result.append_display(self);
452 core::fmt::Display::fmt(&result.into_managed_buffer(), f)
453 }
454}
455
456impl<M: ManagedTypeApi, D: Decimals> core::fmt::Debug for ManagedDecimalSigned<M, D> {
457 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
458 f.debug_struct("ManagedDecimalSigned")
459 .field("handle", &self.data.handle.clone())
460 .field("number", &self.to_string())
461 .finish()
462 }
463}