multiversx_sc/io/
finish.rs1use core::marker::PhantomData;
2
3use unwrap_infallible::UnwrapInfallible;
4
5use crate::codec::{EncodeErrorHandler, TopEncodeMulti, TopEncodeMultiOutput, TryStaticCast};
6
7use crate::{
8 api::{EndpointFinishApi, EndpointFinishApiImpl, ManagedTypeApi},
9 codec::{EncodeError, TopEncode, TopEncodeOutput},
10 contract_base::ExitCodecErrorHandler,
11 err_msg,
12 types::{
13 BigInt, BigUint, ManagedBuffer, ManagedBufferBuilder, ManagedSCError, ManagedType, SCError,
14 StaticSCError,
15 },
16};
17
18pub fn finish_multi<FA, T>(item: &T)
19where
20 FA: ManagedTypeApi + EndpointFinishApi,
21 T: TopEncodeMulti,
22{
23 let h = ExitCodecErrorHandler::<FA>::from(err_msg::FINISH_ENCODE_ERROR);
24 let mut output = ApiOutputAdapter::<FA>::default();
25 item.multi_encode_or_handle_err(&mut output, h)
26 .unwrap_infallible()
27}
28
29#[derive(Clone)]
30pub struct ApiOutputAdapter<FA>
31where
32 FA: ManagedTypeApi + EndpointFinishApi,
33{
34 _phantom: PhantomData<FA>,
35}
36
37impl<FA> Default for ApiOutputAdapter<FA>
38where
39 FA: ManagedTypeApi + EndpointFinishApi,
40{
41 #[inline]
42 fn default() -> Self {
43 ApiOutputAdapter {
44 _phantom: PhantomData,
45 }
46 }
47}
48
49impl<FA> TopEncodeOutput for ApiOutputAdapter<FA>
50where
51 FA: ManagedTypeApi + EndpointFinishApi,
52{
53 type NestedBuffer = ManagedBufferBuilder<FA>;
54
55 fn set_slice_u8(self, bytes: &[u8]) {
56 FA::finish_api_impl().finish_slice_u8(bytes);
57 }
58
59 fn set_u64(self, value: u64) {
60 FA::finish_api_impl().finish_u64(value);
61 }
62
63 fn set_i64(self, value: i64) {
64 FA::finish_api_impl().finish_i64(value);
65 }
66
67 #[inline]
68 fn set_unit(self) {
69 }
71
72 #[inline]
73 fn supports_specialized_type<T: TryStaticCast>() -> bool {
74 T::type_eq::<ManagedBuffer<FA>>()
75 || T::type_eq::<BigUint<FA>>()
76 || T::type_eq::<BigInt<FA>>()
77 }
78
79 #[inline]
80 fn set_specialized<T, H>(self, value: &T, h: H) -> Result<(), H::HandledErr>
81 where
82 T: TryStaticCast,
83 H: EncodeErrorHandler,
84 {
85 if let Some(managed_buffer) = value.try_cast_ref::<ManagedBuffer<FA>>() {
86 FA::finish_api_impl().finish_managed_buffer_raw(managed_buffer.handle.clone());
87 Ok(())
88 } else if let Some(big_uint) = value.try_cast_ref::<BigUint<FA>>() {
89 FA::finish_api_impl().finish_big_uint_raw(big_uint.value.handle.clone());
90 Ok(())
91 } else if let Some(big_int) = value.try_cast_ref::<BigInt<FA>>() {
92 FA::finish_api_impl().finish_big_int_raw(big_int.handle.clone());
93 Ok(())
94 } else {
95 Err(h.handle_error(EncodeError::UNSUPPORTED_OPERATION))
96 }
97 }
98
99 fn start_nested_encode(&self) -> Self::NestedBuffer {
100 ManagedBufferBuilder::new_from_slice(&[])
101 }
102
103 fn finalize_nested_encode(self, nb: Self::NestedBuffer) {
104 FA::finish_api_impl().finish_managed_buffer_raw(nb.into_managed_buffer().get_handle());
105 }
106}
107
108impl<FA> TopEncodeMultiOutput for ApiOutputAdapter<FA>
109where
110 FA: ManagedTypeApi + EndpointFinishApi,
111{
112 fn push_single_value<T, H>(&mut self, arg: &T, h: H) -> Result<(), H::HandledErr>
113 where
114 T: TopEncode,
115 H: EncodeErrorHandler,
116 {
117 arg.top_encode_or_handle_err(self.clone(), h)
118 }
119
120 fn push_multi_specialized<T, H>(&mut self, arg: &T, h: H) -> Result<(), H::HandledErr>
121 where
122 T: TryStaticCast,
123 H: EncodeErrorHandler,
124 {
125 if let Some(static_err) = arg.try_cast_ref::<StaticSCError>() {
126 static_err.finish_err::<FA>()
127 } else if let Some(managed_err) = arg.try_cast_ref::<ManagedSCError<FA>>() {
128 managed_err.finish_err::<FA>()
129 } else {
130 Err(h.handle_error(EncodeError::UNSUPPORTED_OPERATION))
131 }
132 }
133}