ink_primitives/sol/
encodable.rs1use alloy_sol_types::utils::words_for_len;
16use ink_prelude::vec::Vec;
17
18use super::encoder::Encoder;
19
20pub trait Encodable: private::Sealed {
38 const DYNAMIC: bool;
40
41 fn head_words(&self) -> usize;
43
44 fn tail_words(&self) -> usize;
46
47 #[inline(always)]
49 fn total_words(&self) -> usize {
50 self.head_words() + self.tail_words()
51 }
52
53 fn head_append(&self, encoder: &mut Encoder);
55
56 fn tail_append(&self, encoder: &mut Encoder);
58
59 fn encode(&self, encoder: &mut Encoder) {
61 if <Self as Encodable>::DYNAMIC {
62 let mut main_encoder = encoder.segment(self.head_words());
64 Encodable::head_append(self, &mut main_encoder);
65 let mut tail_encoder = main_encoder.take_tail(self.tail_words());
67 Encodable::tail_append(self, &mut tail_encoder);
68 } else {
69 Encodable::head_append(self, encoder);
71 }
72 }
73}
74
75#[derive(Debug)]
78pub enum TokenOrDefault<T, D> {
79 Token(T),
80 Default(D),
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub struct FixedSizeDefault(usize);
86
87impl FixedSizeDefault {
88 pub const EMPTY: Self = Self(0);
90
91 pub const WORD: Self = Self(1);
93
94 pub const fn words(size: usize) -> Self {
96 Self(size)
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub struct DynSizeDefault;
103
104impl Encodable for FixedSizeDefault {
105 const DYNAMIC: bool = false;
106
107 fn head_words(&self) -> usize {
108 self.0
110 }
111
112 fn tail_words(&self) -> usize {
113 0
115 }
116
117 fn head_append(&self, encoder: &mut Encoder) {
118 match self.0 {
119 0 => (),
120 n => {
121 encoder.fill(0, n);
123 }
124 }
125 }
126
127 fn tail_append(&self, _: &mut Encoder) {}
128}
129
130impl private::Sealed for FixedSizeDefault {}
131
132impl Encodable for DynSizeDefault {
133 const DYNAMIC: bool = true;
134
135 fn head_words(&self) -> usize {
136 1
138 }
139
140 fn tail_words(&self) -> usize {
141 1
143 }
144
145 fn head_append(&self, encoder: &mut Encoder) {
146 encoder.append_offset();
148 }
149
150 fn tail_append(&self, encoder: &mut Encoder) {
151 encoder.append_length(0);
152 }
153}
154
155impl private::Sealed for DynSizeDefault {}
156
157impl<T, D> Encodable for TokenOrDefault<T, D>
158where
159 T: Encodable,
160 D: Encodable,
161{
162 const DYNAMIC: bool = T::DYNAMIC;
163
164 fn head_words(&self) -> usize {
165 match self {
166 TokenOrDefault::Token(token) => token.head_words(),
167 TokenOrDefault::Default(default) => default.head_words(),
168 }
169 }
170
171 fn tail_words(&self) -> usize {
172 match self {
173 TokenOrDefault::Token(token) => token.tail_words(),
174 TokenOrDefault::Default(default) => default.tail_words(),
175 }
176 }
177
178 fn head_append(&self, encoder: &mut Encoder) {
179 match self {
180 TokenOrDefault::Token(token) => token.head_append(encoder),
181 TokenOrDefault::Default(default) => default.head_append(encoder),
182 }
183 }
184
185 fn tail_append(&self, encoder: &mut Encoder) {
186 match self {
187 TokenOrDefault::Token(token) => token.tail_append(encoder),
188 TokenOrDefault::Default(default) => default.tail_append(encoder),
189 }
190 }
191}
192
193impl<T, D> private::Sealed for TokenOrDefault<T, D> {}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202#[repr(transparent)]
203pub struct Word(pub [u8; 32]);
204
205impl Encodable for Word {
209 const DYNAMIC: bool = false;
210
211 fn head_words(&self) -> usize {
212 1
214 }
215
216 fn tail_words(&self) -> usize {
217 0
219 }
220
221 fn head_append(&self, encoder: &mut Encoder) {
222 encoder.append_word(self.0);
224 }
225
226 fn tail_append(&self, _: &mut Encoder) {}
227}
228
229impl private::Sealed for Word {}
230
231impl<T, const N: usize> Encodable for [T; N]
236where
237 T: Encodable,
238{
239 const DYNAMIC: bool = T::DYNAMIC;
240
241 fn head_words(&self) -> usize {
242 if Self::DYNAMIC {
243 1
245 } else {
246 self.iter().map(T::total_words).sum()
248 }
249 }
250
251 fn tail_words(&self) -> usize {
252 if Self::DYNAMIC {
253 self.iter().map(T::total_words).sum()
255 } else {
256 0
257 }
258 }
259
260 fn head_append(&self, encoder: &mut Encoder) {
261 if Self::DYNAMIC {
262 encoder.append_offset();
264 } else {
265 for inner in self {
267 inner.head_append(encoder);
268 }
269 }
270 }
271
272 fn tail_append(&self, encoder: &mut Encoder) {
273 if Self::DYNAMIC {
275 encode_sequence(self, encoder);
276 }
277 }
278}
279
280impl<T, const N: usize> private::Sealed for [T; N] {}
281
282impl<T> Encodable for Vec<T>
287where
288 T: Encodable,
289{
290 const DYNAMIC: bool = true;
291
292 fn head_words(&self) -> usize {
293 1
295 }
296
297 fn tail_words(&self) -> usize {
298 1 + self.iter().map(T::total_words).sum::<usize>()
300 }
301
302 fn head_append(&self, encoder: &mut Encoder) {
303 encoder.append_offset();
305 }
306
307 fn tail_append(&self, encoder: &mut Encoder) {
308 encoder.append_length(self.len());
310
311 encode_sequence(self, encoder);
313 }
314}
315
316impl<T> private::Sealed for Vec<T> {}
317
318impl Encodable for &[u8] {
322 const DYNAMIC: bool = true;
323
324 fn head_words(&self) -> usize {
325 1
327 }
328
329 fn tail_words(&self) -> usize {
330 1 + words_for_len(self.len())
332 }
333
334 fn head_append(&self, encoder: &mut Encoder) {
335 encoder.append_offset();
337 }
338
339 fn tail_append(&self, encoder: &mut Encoder) {
340 encoder.append_length(self.len());
342 encoder.append_bytes(self);
343 }
344}
345
346impl private::Sealed for &[u8] {}
347
348fn encode_sequence<T>(tokens: &[T], encoder: &mut Encoder)
355where
356 T: Encodable,
357{
358 if T::DYNAMIC {
359 let head_words = tokens.iter().map(T::head_words).sum();
360 let mut main_encoder = encoder.segment(head_words);
361 for inner in tokens {
362 inner.head_append(&mut main_encoder);
363 let mut tail_encoder = main_encoder.take_tail(inner.tail_words());
364 inner.tail_append(&mut tail_encoder);
365 }
366 } else {
367 tokens.iter().for_each(|inner| inner.head_append(encoder));
368 }
369}
370
371pub trait EncodableParams: private::Sealed {
377 fn encode_params(&self, encoder: &mut Encoder);
379}
380
381macro_rules! impl_encodable_params {
384 ($source: ident, $encoder: ident => ($($ty:ident),+$(,)*)) => {
385 let ($($ty,)+) = $source;
386
387 if Self::DYNAMIC {
388 let head_words = 0 $( + $ty.head_words() )+;
389 let mut main_encoder = $encoder.segment(head_words);
390
391 $(
392 $ty.head_append(&mut main_encoder);
393 if $ty::DYNAMIC {
394 let mut tail_encoder = main_encoder.take_tail($ty.tail_words());
395 $ty.tail_append(&mut tail_encoder);
396 }
397 )+
398 } else {
399 $( $ty.head_append($encoder); )+
400 }
401 };
402}
403
404macro_rules! impl_encodable {
411 ($($ty:ident),+) => {
412 #[allow(non_snake_case)]
413 impl<$($ty: Encodable,)+> Encodable for ($($ty,)+) {
414 const DYNAMIC: bool = $(<$ty as Encodable>::DYNAMIC )||+;
415
416 #[inline]
417 fn head_words(&self) -> usize {
418 if Self::DYNAMIC {
419 1
421 } else {
422 let ($($ty,)+) = self;
424 0 $( + $ty.total_words() )+
425 }
426 }
427
428 #[inline]
429 fn tail_words(&self) -> usize {
430 if Self::DYNAMIC {
431 let ($($ty,)+) = self;
433 0 $( + $ty.total_words() )+
434 } else {
435 0
436 }
437 }
438
439 #[inline]
440 fn head_append(&self, encoder: &mut Encoder) {
441 if Self::DYNAMIC {
442 encoder.append_offset();
443 } else {
444 let ($($ty,)+) = self;
445 $(
446 $ty.head_append(encoder);
447 )+
448 }
449 }
450
451 #[inline]
452 fn tail_append(&self, encoder: &mut Encoder) {
453 if Self::DYNAMIC {
454 impl_encodable_params!(self, encoder => ($($ty,)+));
455 }
456 }
457 }
458
459 #[allow(non_snake_case)]
460 impl<$($ty: Encodable,)+> EncodableParams for ($($ty,)+) {
461 fn encode_params(&self, encoder: &mut Encoder) {
462 impl_encodable_params!(self, encoder => ($($ty,)+));
463 }
464 }
465
466 impl<$($ty: Encodable,)+> private::Sealed for ($($ty,)+) {}
467 };
468}
469
470impl_all_tuples!(@nonempty impl_encodable);
471
472impl Encodable for () {
477 const DYNAMIC: bool = false;
478
479 #[inline]
480 fn head_words(&self) -> usize {
481 0
482 }
483
484 #[inline]
485 fn tail_words(&self) -> usize {
486 0
487 }
488
489 #[inline]
490 fn head_append(&self, _: &mut Encoder) {}
491
492 #[inline]
493 fn tail_append(&self, _: &mut Encoder) {}
494
495 #[inline]
496 fn encode(&self, _: &mut Encoder) {}
497}
498
499impl EncodableParams for () {
500 fn encode_params(&self, _: &mut Encoder) {}
501}
502
503impl private::Sealed for () {}
504
505pub(super) mod private {
506 pub trait Sealed {}
508}