1use numbat_codec::TryStaticCast;
2
3use crate::{
4 api::{EndpointFinishApi, ErrorApi, ManagedTypeApi},
5 numbat_codec::{EncodeError, TopEncode, TopEncodeOutput},
6 err_msg,
7 types::{BigInt, BigUint, ManagedBuffer, ManagedType},
8};
9
10struct ApiOutputAdapter<FA>
11where
12 FA: ManagedTypeApi + EndpointFinishApi + Clone + 'static,
13{
14 api: FA,
15}
16
17impl<FA> ApiOutputAdapter<FA>
18where
19 FA: ManagedTypeApi + EndpointFinishApi + Clone + 'static,
20{
21 #[inline]
22 fn new(api: FA) -> Self {
23 ApiOutputAdapter { api }
24 }
25}
26
27impl<FA> TopEncodeOutput for ApiOutputAdapter<FA>
28where
29 FA: ManagedTypeApi + EndpointFinishApi + Clone + 'static,
30{
31 type NestedBuffer = ManagedBuffer<FA>;
32
33 fn set_slice_u8(self, bytes: &[u8]) {
34 self.api.finish_slice_u8(bytes);
35 }
36
37 fn set_u64(self, value: u64) {
38 self.api.finish_u64(value);
39 }
40
41 fn set_i64(self, value: i64) {
42 self.api.finish_i64(value);
43 }
44
45 #[inline]
46 fn set_unit(self) {
47 }
49
50 #[inline]
51 fn set_specialized<T, F>(self, value: &T, else_serialization: F) -> Result<(), EncodeError>
52 where
53 T: TryStaticCast,
54 F: FnOnce(Self) -> Result<(), EncodeError>,
55 {
56 if let Some(managed_buffer) = value.try_cast_ref::<ManagedBuffer<FA>>() {
57 self.api.finish_managed_buffer_raw(managed_buffer.handle);
58 Ok(())
59 } else if let Some(big_uint) = value.try_cast_ref::<BigUint<FA>>() {
60 self.api.finish_big_uint_raw(big_uint.handle);
61 Ok(())
62 } else if let Some(big_int) = value.try_cast_ref::<BigInt<FA>>() {
63 self.api.finish_big_int_raw(big_int.handle);
64 Ok(())
65 } else {
66 else_serialization(self)
67 }
68 }
69
70 fn start_nested_encode(&self) -> Self::NestedBuffer {
71 ManagedBuffer::new(self.api.clone())
72 }
73
74 fn finalize_nested_encode(self, nb: Self::NestedBuffer) {
75 self.api.finish_managed_buffer_raw(nb.handle);
76 }
77}
78
79pub trait EndpointResult: Sized {
81 type DecodeAs;
84
85 fn finish<FA>(&self, api: FA)
86 where
87 FA: ManagedTypeApi + EndpointFinishApi + Clone + 'static;
88}
89
90impl<T> EndpointResult for T
92where
93 T: TopEncode,
94{
95 type DecodeAs = Self;
96
97 fn finish<FA>(&self, api: FA)
98 where
99 FA: ManagedTypeApi + EndpointFinishApi + Clone + 'static,
100 {
101 self.top_encode_or_exit(ApiOutputAdapter::new(api.clone()), api, finish_exit);
102 }
103}
104
105#[inline(always)]
106fn finish_exit<FA>(api: FA, encode_err: EncodeError) -> !
107where
108 FA: ManagedTypeApi + EndpointFinishApi + ErrorApi + 'static,
109{
110 let mut message_buffer =
111 ManagedBuffer::new_from_bytes(api.clone(), err_msg::FINISH_ENCODE_ERROR);
112 message_buffer.append_bytes(encode_err.message_bytes());
113 api.signal_error_from_buffer(message_buffer.get_raw_handle())
114}