1use crate::{
15 abi::{Decoder, Encoder},
16 Result, Word,
17};
18use alloc::vec::Vec;
19use alloy_primitives::{utils::vec_try_with_capacity, Bytes, FixedBytes, I256, U256};
20use core::fmt;
21
22#[allow(unknown_lints, unnameable_types)]
23mod sealed {
24 pub trait Sealed {}
25 impl Sealed for super::WordToken {}
26 impl Sealed for () {}
27 impl<T, const N: usize> Sealed for super::FixedSeqToken<T, N> {}
28 impl<T> Sealed for super::DynSeqToken<T> {}
29 impl Sealed for super::PackedSeqToken<'_> {}
30}
31use sealed::Sealed;
32
33pub trait Token<'de>: Sealed + Sized {
55 const DYNAMIC: bool;
57
58 fn decode_from(dec: &mut Decoder<'de>) -> Result<Self>;
60
61 fn head_words(&self) -> usize;
63
64 fn tail_words(&self) -> usize;
66
67 #[inline]
69 fn total_words(&self) -> usize {
70 self.head_words() + self.tail_words()
71 }
72
73 fn head_append(&self, enc: &mut Encoder);
75
76 fn tail_append(&self, enc: &mut Encoder);
78}
79
80pub trait TokenSeq<'a>: Token<'a> {
86 const IS_TUPLE: bool = false;
88
89 fn encode_sequence(&self, enc: &mut Encoder);
91
92 fn decode_sequence(dec: &mut Decoder<'a>) -> Result<Self>;
94}
95
96#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
98pub struct WordToken(pub Word);
99
100impl<T> From<&T> for WordToken
101where
102 T: Clone,
103 Self: From<T>,
104{
105 #[inline]
106 fn from(value: &T) -> Self {
107 Self::from(value.clone())
108 }
109}
110
111impl<T> From<&mut T> for WordToken
112where
113 T: Clone,
114 Self: From<T>,
115{
116 #[inline]
117 fn from(value: &mut T) -> Self {
118 Self::from(value.clone())
119 }
120}
121
122impl From<Word> for WordToken {
123 #[inline]
124 fn from(value: Word) -> Self {
125 Self(value)
126 }
127}
128
129impl From<WordToken> for Word {
130 #[inline]
131 fn from(value: WordToken) -> Self {
132 value.0
133 }
134}
135
136impl From<bool> for WordToken {
137 #[inline]
138 fn from(value: bool) -> Self {
139 U256::from(value as u64).into()
140 }
141}
142
143impl From<U256> for WordToken {
144 #[inline]
145 fn from(value: U256) -> Self {
146 Self(value.into())
147 }
148}
149
150impl From<I256> for WordToken {
151 #[inline]
152 fn from(value: I256) -> Self {
153 Self(value.into())
154 }
155}
156
157impl From<WordToken> for [u8; 32] {
158 #[inline]
159 fn from(value: WordToken) -> [u8; 32] {
160 value.0.into()
161 }
162}
163
164impl From<[u8; 32]> for WordToken {
165 #[inline]
166 fn from(value: [u8; 32]) -> Self {
167 Self(value.into())
168 }
169}
170
171impl AsRef<Word> for WordToken {
172 #[inline]
173 fn as_ref(&self) -> &Word {
174 &self.0
175 }
176}
177
178impl AsRef<[u8]> for WordToken {
179 #[inline]
180 fn as_ref(&self) -> &[u8] {
181 &self.0 .0
182 }
183}
184
185impl<'a> Token<'a> for WordToken {
186 const DYNAMIC: bool = false;
187
188 #[inline]
189 fn decode_from(dec: &mut Decoder<'a>) -> Result<Self> {
190 dec.take_word().copied().map(Self)
191 }
192
193 #[inline]
194 fn head_words(&self) -> usize {
195 1
196 }
197
198 #[inline]
199 fn tail_words(&self) -> usize {
200 0
201 }
202
203 #[inline]
204 fn head_append(&self, enc: &mut Encoder) {
205 enc.append_word(self.0);
206 }
207
208 #[inline]
209 fn tail_append(&self, _enc: &mut Encoder) {}
210}
211
212impl WordToken {
213 #[inline]
215 pub const fn new(array: [u8; 32]) -> Self {
216 Self(FixedBytes(array))
217 }
218
219 #[inline]
221 pub const fn as_slice(&self) -> &[u8] {
222 &self.0 .0
223 }
224}
225
226#[derive(Clone, Debug, PartialEq, Eq)]
228pub struct FixedSeqToken<T, const N: usize>(pub [T; N]);
229
230impl<T, const N: usize> TryFrom<Vec<T>> for FixedSeqToken<T, N> {
231 type Error = <[T; N] as TryFrom<Vec<T>>>::Error;
232
233 #[inline]
234 fn try_from(value: Vec<T>) -> Result<Self, Self::Error> {
235 <[T; N]>::try_from(value).map(Self)
236 }
237}
238
239impl<T, const N: usize> From<[T; N]> for FixedSeqToken<T, N> {
240 #[inline]
241 fn from(value: [T; N]) -> Self {
242 Self(value)
243 }
244}
245
246impl<T, const N: usize> AsRef<[T; N]> for FixedSeqToken<T, N> {
247 #[inline]
248 fn as_ref(&self) -> &[T; N] {
249 &self.0
250 }
251}
252
253impl<'de, T: Token<'de>, const N: usize> Token<'de> for FixedSeqToken<T, N> {
254 const DYNAMIC: bool = T::DYNAMIC;
255
256 #[inline]
257 fn decode_from(dec: &mut Decoder<'de>) -> Result<Self> {
258 if Self::DYNAMIC {
259 dec.take_indirection().and_then(|mut child| Self::decode_sequence(&mut child))
260 } else {
261 Self::decode_sequence(dec)
262 }
263 }
264
265 #[inline]
266 fn head_words(&self) -> usize {
267 if Self::DYNAMIC {
268 1
270 } else {
271 self.0.iter().map(T::total_words).sum()
273 }
274 }
275
276 #[inline]
277 fn tail_words(&self) -> usize {
278 if Self::DYNAMIC {
279 self.0.iter().map(T::total_words).sum()
281 } else {
282 0
283 }
284 }
285
286 #[inline]
287 fn head_append(&self, enc: &mut Encoder) {
288 if Self::DYNAMIC {
289 enc.append_indirection();
290 } else {
291 for inner in &self.0 {
292 inner.head_append(enc);
293 }
294 }
295 }
296
297 #[inline]
298 fn tail_append(&self, enc: &mut Encoder) {
299 if Self::DYNAMIC {
300 self.encode_sequence(enc);
301 }
302 }
303}
304
305impl<'de, T: Token<'de>, const N: usize> TokenSeq<'de> for FixedSeqToken<T, N> {
306 fn encode_sequence(&self, enc: &mut Encoder) {
307 enc.push_offset(self.0.iter().map(T::head_words).sum());
308
309 for inner in &self.0 {
310 inner.head_append(enc);
311 enc.bump_offset(inner.tail_words());
312 }
313 for inner in &self.0 {
314 inner.tail_append(enc);
315 }
316
317 enc.pop_offset();
318 }
319
320 #[inline]
321 fn decode_sequence(dec: &mut Decoder<'de>) -> Result<Self> {
322 crate::impl_core::try_from_fn(|_| T::decode_from(dec)).map(Self)
323 }
324}
325
326impl<T, const N: usize> FixedSeqToken<T, N> {
327 #[allow(clippy::missing_const_for_fn)]
330 #[inline]
331 pub fn into_array(self) -> [T; N] {
332 self.0
333 }
334
335 #[inline]
337 pub const fn as_array(&self) -> &[T; N] {
338 &self.0
339 }
340
341 #[inline]
343 pub const fn as_slice(&self) -> &[T] {
344 &self.0
345 }
346}
347
348#[derive(Clone, Debug, PartialEq, Eq)]
350pub struct DynSeqToken<T>(pub Vec<T>);
351
352impl<T> From<Vec<T>> for DynSeqToken<T> {
353 #[inline]
354 fn from(value: Vec<T>) -> Self {
355 Self(value)
356 }
357}
358
359impl<T> AsRef<[T]> for DynSeqToken<T> {
360 #[inline]
361 fn as_ref(&self) -> &[T] {
362 self.0.as_ref()
363 }
364}
365
366impl<'de, T: Token<'de>> Token<'de> for DynSeqToken<T> {
367 const DYNAMIC: bool = true;
368
369 #[inline]
370 fn decode_from(dec: &mut Decoder<'de>) -> Result<Self> {
371 let mut child = dec.take_indirection()?;
372 let len = child.take_offset()?;
373 let mut child = child.raw_child()?;
378 let mut tokens = vec_try_with_capacity(len)?;
379 for _ in 0..len {
380 tokens.push(T::decode_from(&mut child)?);
381 }
382 Ok(Self(tokens))
383 }
384
385 #[inline]
386 fn head_words(&self) -> usize {
387 1
389 }
390
391 #[inline]
392 fn tail_words(&self) -> usize {
393 1 + self.0.iter().map(T::total_words).sum::<usize>()
395 }
396
397 #[inline]
398 fn head_append(&self, enc: &mut Encoder) {
399 enc.append_indirection();
400 }
401
402 #[inline]
403 fn tail_append(&self, enc: &mut Encoder) {
404 enc.append_seq_len(self.0.len());
405 self.encode_sequence(enc);
406 }
407}
408
409impl<'de, T: Token<'de>> TokenSeq<'de> for DynSeqToken<T> {
410 fn encode_sequence(&self, enc: &mut Encoder) {
411 enc.push_offset(self.0.iter().map(T::head_words).sum());
412
413 for inner in &self.0 {
414 inner.head_append(enc);
415 enc.bump_offset(inner.tail_words());
416 }
417 for inner in &self.0 {
418 inner.tail_append(enc);
419 }
420
421 enc.pop_offset();
422 }
423
424 #[inline]
425 fn decode_sequence(dec: &mut Decoder<'de>) -> Result<Self> {
426 Self::decode_from(dec)
427 }
428}
429
430impl<T> DynSeqToken<T> {
431 #[inline]
433 pub fn as_slice(&self) -> &[T] {
434 &self.0
435 }
436}
437
438#[derive(Clone, Copy, PartialEq, Eq)]
440pub struct PackedSeqToken<'a>(pub &'a [u8]);
441
442impl fmt::Debug for PackedSeqToken<'_> {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 f.debug_tuple("PackedSeqToken").field(&hex::encode_prefixed(self.0)).finish()
445 }
446}
447
448impl<'a> From<&'a [u8]> for PackedSeqToken<'a> {
449 fn from(value: &'a [u8]) -> Self {
450 Self(value)
451 }
452}
453
454impl<'a> From<&'a Vec<u8>> for PackedSeqToken<'a> {
455 fn from(value: &'a Vec<u8>) -> Self {
456 Self(value.as_slice())
457 }
458}
459
460impl AsRef<[u8]> for PackedSeqToken<'_> {
461 fn as_ref(&self) -> &[u8] {
462 self.0
463 }
464}
465
466impl<'de: 'a, 'a> Token<'de> for PackedSeqToken<'a> {
467 const DYNAMIC: bool = true;
468
469 #[inline]
470 fn decode_from(dec: &mut Decoder<'de>) -> Result<Self> {
471 let mut child = dec.take_indirection()?;
472 let len = child.take_offset()?;
473 let bytes = child.peek_len(len)?;
474 Ok(PackedSeqToken(bytes))
475 }
476
477 #[inline]
478 fn head_words(&self) -> usize {
479 1
481 }
482
483 #[inline]
484 fn tail_words(&self) -> usize {
485 1 + crate::utils::words_for(self.0)
487 }
488
489 #[inline]
490 fn head_append(&self, enc: &mut Encoder) {
491 enc.append_indirection();
492 }
493
494 #[inline]
495 fn tail_append(&self, enc: &mut Encoder) {
496 enc.append_packed_seq(self.0);
497 }
498}
499
500impl PackedSeqToken<'_> {
501 #[allow(clippy::missing_const_for_fn)]
504 #[inline]
505 pub fn into_vec(self) -> Vec<u8> {
506 self.0.to_vec()
507 }
508
509 pub fn into_bytes(self) -> Bytes {
511 Bytes::copy_from_slice(self.0)
512 }
513
514 #[inline]
516 pub const fn as_slice(&self) -> &[u8] {
517 self.0
518 }
519}
520
521macro_rules! tuple_impls {
522 ($count:literal $($ty:ident),+) => {
523 impl<'de, $($ty: Token<'de>,)+> Sealed for ($($ty,)+) {}
524
525 #[allow(non_snake_case)]
526 impl<'de, $($ty: Token<'de>,)+> Token<'de> for ($($ty,)+) {
527 const DYNAMIC: bool = $( <$ty as Token>::DYNAMIC )||+;
528
529 #[inline]
530 fn decode_from(dec: &mut Decoder<'de>) -> Result<Self> {
531 if Self::DYNAMIC {
534 dec.take_indirection().and_then(|mut child| Self::decode_sequence(&mut child))
535 } else {
536 Self::decode_sequence(dec)
537 }
538 }
539
540 #[inline]
541 fn head_words(&self) -> usize {
542 if Self::DYNAMIC {
543 1
545 } else {
546 let ($($ty,)+) = self;
548 0 $( + $ty.total_words() )+
549 }
550 }
551
552 #[inline]
553 fn tail_words(&self) -> usize {
554 if Self::DYNAMIC {
555 let ($($ty,)+) = self;
557 0 $( + $ty.total_words() )+
558 } else {
559 0
560 }
561 }
562
563 #[inline]
564 fn head_append(&self, enc: &mut Encoder) {
565 if Self::DYNAMIC {
566 enc.append_indirection();
567 } else {
568 let ($($ty,)+) = self;
569 $(
570 $ty.head_append(enc);
571 )+
572 }
573 }
574
575 #[inline]
576 fn tail_append(&self, enc: &mut Encoder) {
577 if Self::DYNAMIC {
578 self.encode_sequence(enc);
579 }
580 }
581 }
582
583 #[allow(non_snake_case)]
584 impl<'de, $($ty: Token<'de>,)+> TokenSeq<'de> for ($($ty,)+) {
585 const IS_TUPLE: bool = true;
586
587 fn encode_sequence(&self, enc: &mut Encoder) {
588 let ($($ty,)+) = self;
589 enc.push_offset(0 $( + $ty.head_words() )+);
590
591 $(
592 $ty.head_append(enc);
593 enc.bump_offset($ty.tail_words());
594 )+
595
596 $(
597 $ty.tail_append(enc);
598 )+
599
600 enc.pop_offset();
601 }
602
603 #[inline]
604 fn decode_sequence(dec: &mut Decoder<'de>) -> Result<Self> {
605 Ok(($(
606 match <$ty as Token>::decode_from(dec) {
607 Ok(t) => t,
608 Err(e) => return Err(e),
609 },
610 )+))
611 }
612 }
613 };
614}
615
616impl<'de> Token<'de> for () {
617 const DYNAMIC: bool = false;
618
619 #[inline]
620 fn decode_from(_dec: &mut Decoder<'de>) -> Result<Self> {
621 Ok(())
622 }
623
624 #[inline]
625 fn head_words(&self) -> usize {
626 0
627 }
628
629 #[inline]
630 fn tail_words(&self) -> usize {
631 0
632 }
633
634 #[inline]
635 fn head_append(&self, _enc: &mut Encoder) {}
636
637 #[inline]
638 fn tail_append(&self, _enc: &mut Encoder) {}
639}
640
641impl<'de> TokenSeq<'de> for () {
642 const IS_TUPLE: bool = true;
643
644 #[inline]
645 fn encode_sequence(&self, _enc: &mut Encoder) {}
646
647 #[inline]
648 fn decode_sequence(_dec: &mut Decoder<'de>) -> Result<Self> {
649 Ok(())
650 }
651}
652
653all_the_tuples!(tuple_impls);
654
655#[cfg(test)]
656mod tests {
657 use super::*;
658 use crate::{sol_data, SolType};
659 use alloy_primitives::B256;
660
661 macro_rules! assert_type_check {
662 ($sol:ty, $token:expr $(,)?) => {
663 assert!(<$sol>::type_check($token).is_ok())
664 };
665 }
666
667 macro_rules! assert_not_type_check {
668 ($sol:ty, $token:expr $(,)?) => {
669 assert!(<$sol>::type_check($token).is_err())
670 };
671 }
672
673 #[test]
674 fn test_type_check() {
675 assert_type_check!(
676 (sol_data::Uint<256>, sol_data::Bool),
677 &(WordToken(B256::default()), WordToken(B256::default())),
678 );
679
680 assert_not_type_check!(sol_data::Uint<8>, &Word::repeat_byte(0x11).into());
682 assert_not_type_check!(sol_data::Bool, &B256::repeat_byte(0x11).into());
683 assert_not_type_check!(sol_data::FixedBytes<31>, &B256::repeat_byte(0x11).into());
684
685 assert_type_check!(
686 (sol_data::Uint<32>, sol_data::Bool),
687 &(WordToken(B256::default()), WordToken(B256::default())),
688 );
689
690 assert_type_check!(
691 sol_data::Array<sol_data::Bool>,
692 &DynSeqToken(vec![WordToken(B256::default()), WordToken(B256::default()),]),
693 );
694
695 assert_type_check!(
696 sol_data::Array<sol_data::Bool>,
697 &DynSeqToken(vec![WordToken(B256::default()), WordToken(B256::default()),]),
698 );
699 assert_type_check!(
700 sol_data::Array<sol_data::Address>,
701 &DynSeqToken(vec![WordToken(B256::default()), WordToken(B256::default()),]),
702 );
703
704 assert_type_check!(
705 sol_data::FixedArray<sol_data::Bool, 2>,
706 &FixedSeqToken::<_, 2>([
707 WordToken(B256::default()),
708 WordToken(B256::default()),
709 ]),
710 );
711
712 assert_type_check!(
713 sol_data::FixedArray<sol_data::Address, 2>,
714 &FixedSeqToken::<_, 2>([
715 WordToken(B256::default()),
716 WordToken(B256::default()),
717 ]),
718 );
719 }
720}