testnumbat_wasm/abi/
type_abi.rs1use super::*;
2use alloc::{
3 boxed::Box,
4 string::{String, ToString},
5 vec::Vec,
6};
7
8pub trait TypeAbi {
9 fn type_name() -> String {
10 core::any::type_name::<Self>().into()
11 }
12
13 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
18 let type_name = Self::type_name();
19 accumulator.insert(
20 type_name,
21 TypeDescription {
22 docs: &[],
23 name: Self::type_name(),
24 contents: TypeContents::NotSpecified,
25 },
26 );
27 }
28
29 #[doc(hidden)]
30 fn is_multi_arg_or_result() -> bool {
31 false
32 }
33
34 #[doc(hidden)]
42 fn output_abis(output_names: &[&'static str]) -> Vec<OutputAbi> {
43 let mut result = Vec::with_capacity(1);
44 let output_name = if !output_names.is_empty() {
45 output_names[0]
46 } else {
47 ""
48 };
49 result.push(OutputAbi {
50 output_name,
51 type_name: Self::type_name(),
52 multi_result: Self::is_multi_arg_or_result(),
53 });
54 result
55 }
56}
57
58impl TypeAbi for () {
59 fn output_abis(_output_names: &[&'static str]) -> Vec<OutputAbi> {
62 Vec::new()
63 }
64}
65
66impl<T: TypeAbi> TypeAbi for &T {
67 fn type_name() -> String {
68 T::type_name()
69 }
70
71 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
72 T::provide_type_descriptions(accumulator);
73 }
74}
75
76impl<T: TypeAbi> TypeAbi for Box<T> {
77 fn type_name() -> String {
78 T::type_name()
79 }
80
81 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
82 T::provide_type_descriptions(accumulator);
83 }
84}
85
86impl<T: TypeAbi> TypeAbi for &[T] {
87 fn type_name() -> String {
88 let t_name = T::type_name();
89 if t_name == "u8" {
90 return "bytes".into();
91 }
92 let mut repr = String::from("List<");
93 repr.push_str(t_name.as_str());
94 repr.push('>');
95 repr
96 }
97}
98
99impl<T: TypeAbi> TypeAbi for Vec<T> {
100 fn type_name() -> String {
101 <&[T]>::type_name()
102 }
103}
104
105impl<T: TypeAbi> TypeAbi for Box<[T]> {
106 fn type_name() -> String {
107 <&[T]>::type_name()
108 }
109}
110
111impl TypeAbi for String {
112 fn type_name() -> String {
113 "utf-8 string".into()
114 }
115}
116
117impl TypeAbi for &str {
118 fn type_name() -> String {
119 String::type_name()
120 }
121}
122
123impl TypeAbi for Box<str> {
124 fn type_name() -> String {
125 String::type_name()
126 }
127}
128
129macro_rules! type_abi_name_only {
130 ($ty:ty, $name:expr) => {
131 impl TypeAbi for $ty {
132 fn type_name() -> String {
133 String::from($name)
134 }
135
136 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(_: &mut TDC) {}
137 }
138 };
139}
140
141type_abi_name_only!(u8, "u8");
142type_abi_name_only!(u16, "u16");
143type_abi_name_only!(u32, "u32");
144type_abi_name_only!(usize, "u32");
145type_abi_name_only!(u64, "u64");
146
147type_abi_name_only!(i8, "i8");
148type_abi_name_only!(i16, "i16");
149type_abi_name_only!(i32, "i32");
150type_abi_name_only!(isize, "i32");
151type_abi_name_only!(i64, "i64");
152
153type_abi_name_only!(core::num::NonZeroUsize, "NonZeroUsize");
154type_abi_name_only!(bool, "bool");
155
156impl<T: TypeAbi> TypeAbi for Option<T> {
157 fn type_name() -> String {
158 let mut repr = String::from("Option<");
159 repr.push_str(T::type_name().as_str());
160 repr.push('>');
161 repr
162 }
163
164 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
165 T::provide_type_descriptions(accumulator);
166 }
167}
168
169impl<T: TypeAbi, E> TypeAbi for Result<T, E> {
170 fn type_name() -> String {
171 T::type_name()
172 }
173
174 fn output_abis(output_names: &[&'static str]) -> Vec<OutputAbi> {
176 T::output_abis(output_names)
177 }
178
179 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
180 T::provide_type_descriptions(accumulator);
181 }
182}
183
184macro_rules! tuple_impls {
185 ($($len:expr => ($($n:tt $name:ident)+))+) => {
186 $(
187 impl<$($name),+> TypeAbi for ($($name,)+)
188 where
189 $($name: TypeAbi,)+
190 {
191 fn type_name() -> String {
192 let mut repr = String::from("tuple");
193 repr.push_str("<");
194 $(
195 if $n > 0 {
196 repr.push(',');
197 }
198 repr.push_str($name::type_name().as_str());
199 )+
200 repr.push('>');
201 repr
202 }
203
204 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
205 $(
206 $name::provide_type_descriptions(accumulator);
207 )+
208 }
209 }
210 )+
211 }
212}
213
214tuple_impls! {
215 1 => (0 T0)
216 2 => (0 T0 1 T1)
217 3 => (0 T0 1 T1 2 T2)
218 4 => (0 T0 1 T1 2 T2 3 T3)
219 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
220 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
221 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
222 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
223 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
224 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
225 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
226 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
227 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
228 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
229 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
230 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
231}
232
233impl<T: TypeAbi, const N: usize> TypeAbi for [T; N] {
234 fn type_name() -> String {
235 let mut repr = String::from("array");
236 repr.push_str(N.to_string().as_str());
237 repr.push('<');
238 repr.push_str(T::type_name().as_str());
239 repr.push('>');
240 repr
241 }
242
243 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
244 T::provide_type_descriptions(accumulator);
245 }
246}