1use crate::metadata::IoTypeMetadataKind;
2
3macro_rules! forward_option {
5 ($expr:expr) => {{
6 let Some(result) = $expr else {
7 return None;
8 };
9 result
10 }};
11}
12
13pub(super) const fn compact_metadata<'i, 'o>(
14 mut input: &'i [u8],
15 mut output: &'o mut [u8],
16) -> Option<(&'i [u8], &'o mut [u8])> {
17 if input.is_empty() || output.is_empty() {
18 return None;
19 }
20
21 let kind = forward_option!(IoTypeMetadataKind::try_from_u8(input[0]));
22
23 match kind {
24 IoTypeMetadataKind::Unit
25 | IoTypeMetadataKind::Bool
26 | IoTypeMetadataKind::U8
27 | IoTypeMetadataKind::U16
28 | IoTypeMetadataKind::U32
29 | IoTypeMetadataKind::U64
30 | IoTypeMetadataKind::U128
31 | IoTypeMetadataKind::I8
32 | IoTypeMetadataKind::I16
33 | IoTypeMetadataKind::I32
34 | IoTypeMetadataKind::I64
35 | IoTypeMetadataKind::I128 => copy_n_bytes(input, output, 1),
36 IoTypeMetadataKind::Struct => {
37 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
38 compact_struct(input, output, None, false)
39 }
40 IoTypeMetadataKind::Struct0 => {
41 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
42 compact_struct(input, output, Some(0), false)
43 }
44 IoTypeMetadataKind::Struct1 => {
45 output[0] = IoTypeMetadataKind::TupleStruct1 as u8;
47 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
48 compact_struct(input, output, Some(1), false)
49 }
50 IoTypeMetadataKind::Struct2 => {
51 output[0] = IoTypeMetadataKind::TupleStruct2 as u8;
53 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
54 compact_struct(input, output, Some(2), false)
55 }
56 IoTypeMetadataKind::Struct3 => {
57 output[0] = IoTypeMetadataKind::TupleStruct3 as u8;
59 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
60 compact_struct(input, output, Some(3), false)
61 }
62 IoTypeMetadataKind::Struct4 => {
63 output[0] = IoTypeMetadataKind::TupleStruct4 as u8;
65 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
66 compact_struct(input, output, Some(4), false)
67 }
68 IoTypeMetadataKind::Struct5 => {
69 output[0] = IoTypeMetadataKind::TupleStruct5 as u8;
71 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
72 compact_struct(input, output, Some(5), false)
73 }
74 IoTypeMetadataKind::Struct6 => {
75 output[0] = IoTypeMetadataKind::TupleStruct6 as u8;
77 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
78 compact_struct(input, output, Some(6), false)
79 }
80 IoTypeMetadataKind::Struct7 => {
81 output[0] = IoTypeMetadataKind::TupleStruct7 as u8;
83 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
84 compact_struct(input, output, Some(7), false)
85 }
86 IoTypeMetadataKind::Struct8 => {
87 output[0] = IoTypeMetadataKind::TupleStruct8 as u8;
89 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
90 compact_struct(input, output, Some(8), false)
91 }
92 IoTypeMetadataKind::Struct9 => {
93 output[0] = IoTypeMetadataKind::TupleStruct9 as u8;
95 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
96 compact_struct(input, output, Some(9), false)
97 }
98 IoTypeMetadataKind::Struct10 => {
99 output[0] = IoTypeMetadataKind::TupleStruct10 as u8;
101 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
102 compact_struct(input, output, Some(10), false)
103 }
104 IoTypeMetadataKind::TupleStruct => {
105 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
106 compact_struct(input, output, None, true)
107 }
108 IoTypeMetadataKind::TupleStruct1 => {
109 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
110 compact_struct(input, output, Some(1), true)
111 }
112 IoTypeMetadataKind::TupleStruct2 => {
113 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
114 compact_struct(input, output, Some(2), true)
115 }
116 IoTypeMetadataKind::TupleStruct3 => {
117 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
118 compact_struct(input, output, Some(3), true)
119 }
120 IoTypeMetadataKind::TupleStruct4 => {
121 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
122 compact_struct(input, output, Some(4), true)
123 }
124 IoTypeMetadataKind::TupleStruct5 => {
125 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
126 compact_struct(input, output, Some(5), true)
127 }
128 IoTypeMetadataKind::TupleStruct6 => {
129 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
130 compact_struct(input, output, Some(6), true)
131 }
132 IoTypeMetadataKind::TupleStruct7 => {
133 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
134 compact_struct(input, output, Some(7), true)
135 }
136 IoTypeMetadataKind::TupleStruct8 => {
137 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
138 compact_struct(input, output, Some(8), true)
139 }
140 IoTypeMetadataKind::TupleStruct9 => {
141 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
142 compact_struct(input, output, Some(9), true)
143 }
144 IoTypeMetadataKind::TupleStruct10 => {
145 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
146 compact_struct(input, output, Some(10), true)
147 }
148 IoTypeMetadataKind::Enum => {
149 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
150 compact_enum(input, output, None, true)
151 }
152 IoTypeMetadataKind::Enum1 => {
153 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
154 compact_enum(input, output, Some(1), true)
155 }
156 IoTypeMetadataKind::Enum2 => {
157 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
158 compact_enum(input, output, Some(2), true)
159 }
160 IoTypeMetadataKind::Enum3 => {
161 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
162 compact_enum(input, output, Some(3), true)
163 }
164 IoTypeMetadataKind::Enum4 => {
165 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
166 compact_enum(input, output, Some(4), true)
167 }
168 IoTypeMetadataKind::Enum5 => {
169 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
170 compact_enum(input, output, Some(5), true)
171 }
172 IoTypeMetadataKind::Enum6 => {
173 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
174 compact_enum(input, output, Some(6), true)
175 }
176 IoTypeMetadataKind::Enum7 => {
177 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
178 compact_enum(input, output, Some(7), true)
179 }
180 IoTypeMetadataKind::Enum8 => {
181 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
182 compact_enum(input, output, Some(8), true)
183 }
184 IoTypeMetadataKind::Enum9 => {
185 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
186 compact_enum(input, output, Some(9), true)
187 }
188 IoTypeMetadataKind::Enum10 => {
189 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
190 compact_enum(input, output, Some(10), true)
191 }
192 IoTypeMetadataKind::EnumNoFields => {
193 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
194 compact_enum(input, output, None, false)
195 }
196 IoTypeMetadataKind::EnumNoFields1 => {
197 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
198 compact_enum(input, output, Some(1), false)
199 }
200 IoTypeMetadataKind::EnumNoFields2 => {
201 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
202 compact_enum(input, output, Some(2), false)
203 }
204 IoTypeMetadataKind::EnumNoFields3 => {
205 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
206 compact_enum(input, output, Some(3), false)
207 }
208 IoTypeMetadataKind::EnumNoFields4 => {
209 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
210 compact_enum(input, output, Some(4), false)
211 }
212 IoTypeMetadataKind::EnumNoFields5 => {
213 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
214 compact_enum(input, output, Some(5), false)
215 }
216 IoTypeMetadataKind::EnumNoFields6 => {
217 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
218 compact_enum(input, output, Some(6), false)
219 }
220 IoTypeMetadataKind::EnumNoFields7 => {
221 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
222 compact_enum(input, output, Some(7), false)
223 }
224 IoTypeMetadataKind::EnumNoFields8 => {
225 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
226 compact_enum(input, output, Some(8), false)
227 }
228 IoTypeMetadataKind::EnumNoFields9 => {
229 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
230 compact_enum(input, output, Some(9), false)
231 }
232 IoTypeMetadataKind::EnumNoFields10 => {
233 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
234 compact_enum(input, output, Some(10), false)
235 }
236 IoTypeMetadataKind::Array8b | IoTypeMetadataKind::VariableElements8b => {
237 (input, output) = forward_option!(copy_n_bytes(input, output, 1 + 1));
238 compact_metadata(input, output)
239 }
240 IoTypeMetadataKind::Array16b | IoTypeMetadataKind::VariableElements16b => {
241 (input, output) = forward_option!(copy_n_bytes(input, output, 1 + 2));
242 compact_metadata(input, output)
243 }
244 IoTypeMetadataKind::Array32b | IoTypeMetadataKind::VariableElements32b => {
245 (input, output) = forward_option!(copy_n_bytes(input, output, 1 + 4));
246 compact_metadata(input, output)
247 }
248 IoTypeMetadataKind::ArrayU8x8
249 | IoTypeMetadataKind::ArrayU8x16
250 | IoTypeMetadataKind::ArrayU8x32
251 | IoTypeMetadataKind::ArrayU8x64
252 | IoTypeMetadataKind::ArrayU8x128
253 | IoTypeMetadataKind::ArrayU8x256
254 | IoTypeMetadataKind::ArrayU8x512
255 | IoTypeMetadataKind::ArrayU8x1024
256 | IoTypeMetadataKind::ArrayU8x2028
257 | IoTypeMetadataKind::ArrayU8x4096 => copy_n_bytes(input, output, 1),
258 IoTypeMetadataKind::VariableBytes8b
259 | IoTypeMetadataKind::FixedCapacityBytes8b
260 | IoTypeMetadataKind::FixedCapacityString8b => copy_n_bytes(input, output, 1 + 1),
261 IoTypeMetadataKind::VariableBytes16b
262 | IoTypeMetadataKind::FixedCapacityBytes16b
263 | IoTypeMetadataKind::FixedCapacityString16b => copy_n_bytes(input, output, 1 + 2),
264 IoTypeMetadataKind::VariableBytes32b => copy_n_bytes(input, output, 1 + 4),
265 IoTypeMetadataKind::VariableBytes0
266 | IoTypeMetadataKind::VariableBytes512
267 | IoTypeMetadataKind::VariableBytes1024
268 | IoTypeMetadataKind::VariableBytes2028
269 | IoTypeMetadataKind::VariableBytes4096
270 | IoTypeMetadataKind::VariableBytes8192
271 | IoTypeMetadataKind::VariableBytes16384
272 | IoTypeMetadataKind::VariableBytes32768
273 | IoTypeMetadataKind::VariableBytes65536
274 | IoTypeMetadataKind::VariableBytes131072
275 | IoTypeMetadataKind::VariableBytes262144
276 | IoTypeMetadataKind::VariableBytes524288
277 | IoTypeMetadataKind::VariableBytes1048576 => copy_n_bytes(input, output, 1),
278 IoTypeMetadataKind::VariableElements0 => {
279 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
280 compact_metadata(input, output)
281 }
282 IoTypeMetadataKind::Address | IoTypeMetadataKind::Balance => copy_n_bytes(input, output, 1),
283 }
284}
285
286const fn compact_struct<'i, 'o>(
287 mut input: &'i [u8],
288 mut output: &'o mut [u8],
289 arguments_count: Option<u8>,
290 tuple: bool,
291) -> Option<(&'i [u8], &'o mut [u8])> {
292 if input.is_empty() || output.is_empty() {
293 return None;
294 }
295
296 let struct_name_length = input[0] as usize;
298 output[0] = 0;
299 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
300 input = forward_option!(skip_n_bytes(input, struct_name_length));
301
302 let mut arguments_count = if let Some(arguments_count) = arguments_count {
303 arguments_count
304 } else {
305 if input.is_empty() || output.is_empty() {
306 return None;
307 }
308
309 let arguments_count = input[0];
310 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
311
312 arguments_count
313 };
314
315 while arguments_count > 0 {
317 if input.is_empty() || output.is_empty() {
318 return None;
319 }
320
321 if !tuple {
323 let field_name_length = input[0] as usize;
324 input = forward_option!(skip_n_bytes(input, 1 + field_name_length));
325 }
326
327 (input, output) = forward_option!(compact_metadata(input, output));
329
330 arguments_count -= 1;
331 }
332
333 Some((input, output))
334}
335
336const fn compact_enum<'i, 'o>(
337 mut input: &'i [u8],
338 mut output: &'o mut [u8],
339 variant_count: Option<u8>,
340 has_fields: bool,
341) -> Option<(&'i [u8], &'o mut [u8])> {
342 if input.is_empty() || output.is_empty() {
343 return None;
344 }
345
346 let enum_name_length = input[0] as usize;
348 output[0] = 0;
349 (input, output) = forward_option!(skip_n_bytes_io(input, output, 1));
350 input = forward_option!(skip_n_bytes(input, enum_name_length));
351
352 let mut variant_count = if let Some(variant_count) = variant_count {
353 variant_count
354 } else {
355 if input.is_empty() || output.is_empty() {
356 return None;
357 }
358
359 let variant_count = input[0];
360 (input, output) = forward_option!(copy_n_bytes(input, output, 1));
361
362 variant_count
363 };
364
365 while variant_count > 0 {
367 if input.is_empty() || output.is_empty() {
368 return None;
369 }
370
371 if has_fields {
372 (input, output) = forward_option!(compact_struct(input, output, None, false));
374 } else {
375 (input, output) = forward_option!(compact_struct(input, output, Some(0), false));
377 }
378
379 variant_count -= 1;
380 }
381
382 Some((input, output))
383}
384
385const fn copy_n_bytes<'i, 'o>(
387 mut input: &'i [u8],
388 mut output: &'o mut [u8],
389 n: usize,
390) -> Option<(&'i [u8], &'o mut [u8])> {
391 if n > input.len() || n > output.len() {
392 return None;
393 }
394
395 let source;
396 let target;
397 (source, input) = input.split_at(n);
398 (target, output) = output.split_at_mut(n);
399 target.copy_from_slice(source);
400
401 Some((input, output))
402}
403
404const fn skip_n_bytes(input: &[u8], n: usize) -> Option<&[u8]> {
406 if n > input.len() {
407 return None;
408 }
409
410 Some(input.split_at(n).1)
412}
413
414const fn skip_n_bytes_io<'i, 'o>(
416 mut input: &'i [u8],
417 mut output: &'o mut [u8],
418 n: usize,
419) -> Option<(&'i [u8], &'o mut [u8])> {
420 if n > input.len() || n > output.len() {
421 return None;
422 }
423
424 input = input.split_at(n).1;
426 output = output.split_at_mut(n).1;
428
429 Some((input, output))
430}