1use bobcat_maths::U;
2
3use bobcat_storage::{Keccak256, keccak256_builder};
4
5#[cfg(feature = "alloc")]
6extern crate alloc;
7
8#[cfg(feature = "alloc")]
9use alloc::{string::String, vec::Vec};
10
11#[cfg(not(feature = "std"))]
12mod no_std {
13 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
14 pub enum Error {
15 WriteAllEof,
16 ReadExactEof,
17 InvalidData,
18 }
19
20 pub trait Write {
21 fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
22 fn flush(&mut self) -> Result<(), Error>;
23 fn is_empty(&self) -> bool;
24
25 fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Error> {
26 while !buf.is_empty() {
27 match self.write(buf) {
28 Ok(0) => return Err(Error::WriteAllEof),
29 Ok(n) if n <= buf.len() => buf = &buf[n..],
30 Ok(_) => return Err(Error::InvalidData),
31 Err(error) => return Err(error),
32 }
33 }
34 Ok(())
35 }
36 }
37
38 pub trait Read {
39 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
40
41 fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Error> {
42 while !buf.is_empty() {
43 match self.read(buf) {
44 Ok(0) => break,
45 Ok(n) if n <= buf.len() => buf = &mut buf[n..],
46 Ok(_) => return Err(Error::InvalidData),
47 Err(error) => return Err(error),
48 }
49 }
50 if buf.is_empty() {
51 Ok(())
52 } else {
53 Err(Error::ReadExactEof)
54 }
55 }
56 }
57
58 impl Write for &mut [u8] {
59 fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
60 let len = core::cmp::min(self.len(), buf.len());
61 let target = core::mem::take(self);
62 let (written, remaining) = target.split_at_mut(len);
63 written.copy_from_slice(&buf[..len]);
64 *self = remaining;
65 Ok(len)
66 }
67
68 fn flush(&mut self) -> Result<(), Error> {
69 Ok(())
70 }
71
72 fn is_empty(&self) -> bool {
73 <[u8]>::is_empty(self)
74 }
75 }
76
77 impl Read for &[u8] {
78 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
79 let len = core::cmp::min(self.len(), buf.len());
80 buf[..len].copy_from_slice(&self[..len]);
81 *self = &self[len..];
82 Ok(len)
83 }
84 }
85}
86
87#[cfg(not(feature = "std"))]
88pub use no_std::{Error, Read, Write};
89
90#[cfg(feature = "std")]
91pub use std::io::{Error, Read, Write};
92
93#[doc(hidden)]
94#[derive(Clone)]
95pub struct SelectorHasher(Keccak256);
96
97impl SelectorHasher {
98 pub fn new() -> Self {
99 Self(keccak256_builder())
100 }
101
102 pub fn update(self, bytes: &[u8]) -> Self {
103 Self(self.0.update(bytes))
104 }
105
106 pub fn update_usize(self, mut value: usize) -> Self {
107 let mut digits = [0u8; 20];
108 let mut start = digits.len();
109 loop {
110 start -= 1;
111 digits[start] = b'0' + (value % 10) as u8;
112 value /= 10;
113 if value == 0 {
114 break;
115 }
116 }
117 self.update(&digits[start..])
118 }
119
120 pub fn selector(&self) -> [u8; 4] {
121 let hash = self.0.finalize();
122 [hash[0], hash[1], hash[2], hash[3]]
123 }
124}
125
126impl Default for SelectorHasher {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132pub trait EvmCdSerialise {
133 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error>;
134
135 #[doc(hidden)]
136 fn serialise_value<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
137 self.serialise(writer)
138 }
139
140 #[doc(hidden)]
141 fn is_abi_dynamic() -> bool {
142 false
143 }
144
145 #[doc(hidden)]
146 fn abi_head_size() -> usize {
147 32
148 }
149
150 #[doc(hidden)]
151 fn abi_tail_size(&self) -> usize {
152 0
153 }
154
155 #[doc(hidden)]
156 fn serialise_abi_head<W: Write>(
157 &self,
158 _tail_offset: usize,
159 writer: &mut W,
160 ) -> Result<(), Error> {
161 self.serialise_value(writer)
162 }
163
164 #[doc(hidden)]
165 fn serialise_abi_tail<W: Write>(&self, _writer: &mut W) -> Result<(), Error> {
166 Ok(())
167 }
168
169 #[doc(hidden)]
170 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher;
171}
172
173#[doc(hidden)]
174pub enum EvmCdHead<T> {
175 Value(T),
176 Offset(usize),
177}
178
179#[doc(hidden)]
180pub struct EvmCdStaticBufferKind;
181
182#[cfg(feature = "alloc")]
183#[doc(hidden)]
184pub struct EvmCdDynamicBufferKind;
185
186#[doc(hidden)]
187pub trait EvmCdBufferKind {
188 type Buffer<S>: EvmCdDecodeBuffer;
189 type Combined<Rhs: EvmCdBufferKind>: EvmCdBufferKind;
190}
191
192impl EvmCdBufferKind for EvmCdStaticBufferKind {
193 type Buffer<S> = EvmCdBuffer<S>;
194 type Combined<Rhs: EvmCdBufferKind> = Rhs;
195}
196
197#[cfg(feature = "alloc")]
198impl EvmCdBufferKind for EvmCdDynamicBufferKind {
199 type Buffer<S> = EvmCdDynamicBuffer<S>;
200 type Combined<Rhs: EvmCdBufferKind> = EvmCdDynamicBufferKind;
201}
202
203#[doc(hidden)]
204pub trait EvmCdDecodeBuffer: AsRef<[u8]> + AsMut<[u8]> + Sized {
205 type Kind: EvmCdBufferKind;
206
207 fn new(len: usize) -> Result<Self, Error>;
208}
209
210#[doc(hidden)]
211pub struct EvmCdBuffer<S> {
212 storage: core::mem::MaybeUninit<S>,
213}
214
215impl<S> EvmCdDecodeBuffer for EvmCdBuffer<S> {
216 type Kind = EvmCdStaticBufferKind;
217
218 fn new(len: usize) -> Result<Self, Error> {
219 if len > size_of::<S>() {
220 return Err(invalid_data());
221 }
222 let mut storage = core::mem::MaybeUninit::<S>::uninit();
223 unsafe {
226 storage
227 .as_mut_ptr()
228 .cast::<u8>()
229 .write_bytes(0, size_of::<S>())
230 };
231 Ok(Self { storage })
232 }
233}
234
235impl<S> AsRef<[u8]> for EvmCdBuffer<S> {
236 fn as_ref(&self) -> &[u8] {
237 unsafe { core::slice::from_raw_parts(self.storage.as_ptr().cast::<u8>(), size_of::<S>()) }
239 }
240}
241
242impl<S> AsMut<[u8]> for EvmCdBuffer<S> {
243 fn as_mut(&mut self) -> &mut [u8] {
244 unsafe {
246 core::slice::from_raw_parts_mut(self.storage.as_mut_ptr().cast::<u8>(), size_of::<S>())
247 }
248 }
249}
250
251#[cfg(feature = "alloc")]
252#[doc(hidden)]
253pub struct EvmCdDynamicBuffer<S>(Vec<u8>, core::marker::PhantomData<S>);
254
255#[cfg(feature = "alloc")]
256impl<S> EvmCdDecodeBuffer for EvmCdDynamicBuffer<S> {
257 type Kind = EvmCdDynamicBufferKind;
258
259 fn new(len: usize) -> Result<Self, Error> {
260 if len > MAX_ALLOC_DESERIALISE_LEN {
261 return Err(invalid_data());
262 }
263 let mut bytes = Vec::new();
264 bytes.try_reserve_exact(len).map_err(|_| invalid_data())?;
265 bytes.resize(len, 0);
266 Ok(Self(bytes, core::marker::PhantomData))
267 }
268}
269
270#[cfg(feature = "alloc")]
271impl<S> AsRef<[u8]> for EvmCdDynamicBuffer<S> {
272 fn as_ref(&self) -> &[u8] {
273 &self.0
274 }
275}
276
277#[cfg(feature = "alloc")]
278impl<S> AsMut<[u8]> for EvmCdDynamicBuffer<S> {
279 fn as_mut(&mut self) -> &mut [u8] {
280 &mut self.0
281 }
282}
283
284pub trait EvmCdDeserialise: Sized {
285 type Buffer: EvmCdDecodeBuffer;
286
287 fn new_buffer(len: usize) -> Result<Self::Buffer, Error> {
288 Self::Buffer::new(len)
289 }
290
291 fn deserialise<B>(bytes: &B) -> Result<Self, Error>
292 where
293 B: AsRef<[u8]> + ?Sized,
294 {
295 let mut reader = bytes.as_ref();
296 Self::deserialise_reader(&mut reader)
297 }
298
299 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error>;
300
301 #[doc(hidden)]
302 fn deserialise_value<R: Read>(reader: &mut R) -> Result<Self, Error> {
303 Self::deserialise_reader(reader)
304 }
305
306 #[doc(hidden)]
307 fn is_abi_dynamic() -> bool {
308 false
309 }
310
311 #[doc(hidden)]
312 fn abi_head_size() -> usize {
313 32
314 }
315
316 #[doc(hidden)]
317 fn abi_tail_size(&self) -> usize {
318 0
319 }
320
321 #[doc(hidden)]
322 fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
323 Ok(EvmCdHead::Value(Self::deserialise_value(reader)?))
324 }
325
326 #[doc(hidden)]
327 fn deserialise_abi_finish<R: Read>(
328 head: EvmCdHead<Self>,
329 _expected_tail_offset: usize,
330 _reader: &mut R,
331 ) -> Result<Self, Error> {
332 match head {
333 EvmCdHead::Value(value) => Ok(value),
334 EvmCdHead::Offset(_) => Err(invalid_data()),
335 }
336 }
337
338 #[doc(hidden)]
339 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher;
340}
341
342#[cfg(not(feature = "std"))]
343pub fn invalid_data() -> Error {
344 Error::InvalidData
345}
346
347#[cfg(feature = "std")]
348pub fn invalid_data() -> Error {
349 Error::new(std::io::ErrorKind::InvalidData, "invalid EVM calldata")
350}
351
352fn read_usize_word<R: Read>(reader: &mut R) -> Result<usize, Error> {
353 let mut word = [0u8; 32];
354 reader.read_exact(&mut word)?;
355 if word[..32 - size_of::<usize>()]
356 .iter()
357 .any(|byte| *byte != 0)
358 {
359 return Err(invalid_data());
360 }
361 Ok(usize::from_be_bytes(
362 word[32 - size_of::<usize>()..].try_into().unwrap(),
363 ))
364}
365
366fn write_dynamic_tail<W: Write>(bytes: &[u8], writer: &mut W) -> Result<(), Error> {
367 writer.write_all(&U::from_usize(bytes.len()).0)?;
368 writer.write_all(bytes)?;
369 const ZEROES: [u8; 31] = [0; 31];
370 let padding = (32 - bytes.len() % 32) % 32;
371 writer.write_all(&ZEROES[..padding])
372}
373
374fn write_dynamic_bytes<W: Write>(bytes: &[u8], writer: &mut W) -> Result<(), Error> {
375 writer.write_all(&U::from_u32(32).0)?;
376 write_dynamic_tail(bytes, writer)
377}
378
379fn dynamic_tail_size(len: usize) -> usize {
380 32 + len + (32 - len % 32) % 32
381}
382
383fn read_dynamic_tail<const CAP: usize, R: Read>(
384 reader: &mut R,
385) -> Result<([u8; CAP], usize), Error> {
386 let len = read_usize_word(reader)?;
387 if len > CAP {
388 return Err(invalid_data());
389 }
390 let mut bytes = [0u8; CAP];
391 reader.read_exact(&mut bytes[..len])?;
392 let padding = (32 - len % 32) % 32;
393 let mut padding_bytes = [0u8; 31];
394 reader.read_exact(&mut padding_bytes[..padding])?;
395 if padding_bytes[..padding].iter().any(|byte| *byte != 0) {
396 return Err(invalid_data());
397 }
398 Ok((bytes, len))
399}
400
401fn read_dynamic_bytes<const CAP: usize, R: Read>(
402 reader: &mut R,
403) -> Result<([u8; CAP], usize), Error> {
404 if read_usize_word(reader)? != 32 {
405 return Err(invalid_data());
406 }
407 read_dynamic_tail(reader)
408}
409
410macro_rules! fixed_deserialise_buffer {
411 ($storage:ty) => {
412 type Buffer = EvmCdBuffer<$storage>;
413 };
414}
415
416impl EvmCdSerialise for U {
417 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
418 writer.write_all(&self.0)
419 }
420
421 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
422 hasher.update(b"uint256")
423 }
424}
425
426impl EvmCdDeserialise for U {
427 fixed_deserialise_buffer!([u8; 32]);
428
429 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
430 let mut buf = [0u8; 32];
431 reader.read_exact(&mut buf)?;
432 Ok(U(buf))
433 }
434
435 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
436 hasher.update(b"uint256")
437 }
438}
439
440macro_rules! for_ints {
441 ($($ty:ty => $abi:literal),+ $(,)?) => {
442 $(
443 impl EvmCdSerialise for $ty {
444 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
445 writer.write_all(&[0u8; 32 - size_of::<$ty>()])?;
446 writer.write_all(&self.to_be_bytes())
447 }
448
449 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
450 hasher.update($abi)
451 }
452 }
453
454 impl EvmCdDeserialise for $ty {
455 fixed_deserialise_buffer!([u8; 32]);
456
457 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
458 let U(word) = U::deserialise_reader(reader)?;
459 if word[..32 - size_of::<$ty>()].iter().any(|byte| *byte != 0) {
460 return Err(invalid_data());
461 }
462 Ok(<$ty>::from_be_bytes(
463 word[32 - size_of::<$ty>()..].try_into().unwrap(),
464 ))
465 }
466
467 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
468 hasher.update($abi)
469 }
470 }
471 )+
472 };
473}
474
475for_ints! {
476 u8 => b"uint8",
477 u16 => b"uint16",
478 u32 => b"uint32",
479 u64 => b"uint64",
480 u128 => b"uint128",
481}
482
483impl EvmCdSerialise for usize {
484 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
485 u32::try_from(*self)
486 .map_err(|_| invalid_data())?
487 .serialise(writer)
488 }
489
490 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
491 hasher.update(b"uint32")
492 }
493}
494
495impl EvmCdDeserialise for usize {
496 fixed_deserialise_buffer!([u8; 32]);
497
498 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
499 Ok(u32::deserialise_reader(reader)? as usize)
500 }
501
502 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
503 hasher.update(b"uint32")
504 }
505}
506
507#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
508pub struct EvmCdAddress([u8; 20]);
509
510impl EvmCdAddress {
511 pub const fn new(bytes: [u8; 20]) -> Self {
512 Self(bytes)
513 }
514
515 pub const fn into_array(self) -> [u8; 20] {
516 self.0
517 }
518
519 pub const fn as_array(&self) -> &[u8; 20] {
520 &self.0
521 }
522}
523
524impl From<[u8; 20]> for EvmCdAddress {
525 fn from(bytes: [u8; 20]) -> Self {
526 Self::new(bytes)
527 }
528}
529
530impl From<EvmCdAddress> for [u8; 20] {
531 fn from(address: EvmCdAddress) -> Self {
532 address.into_array()
533 }
534}
535
536impl AsRef<[u8; 20]> for EvmCdAddress {
537 fn as_ref(&self) -> &[u8; 20] {
538 self.as_array()
539 }
540}
541
542impl AsRef<[u8]> for EvmCdAddress {
543 fn as_ref(&self) -> &[u8] {
544 self.as_array()
545 }
546}
547
548impl EvmCdSerialise for EvmCdAddress {
549 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
550 writer.write_all(&[0; 12])?;
551 writer.write_all(&self.0)
552 }
553
554 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
555 hasher.update(b"address")
556 }
557}
558
559impl EvmCdDeserialise for EvmCdAddress {
560 fixed_deserialise_buffer!([u8; 32]);
561
562 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
563 let mut word = [0u8; 32];
564 reader.read_exact(&mut word)?;
565 if word[..12].iter().any(|byte| *byte != 0) {
566 return Err(invalid_data());
567 }
568 Ok(Self(word[12..].try_into().unwrap()))
569 }
570
571 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
572 hasher.update(b"address")
573 }
574}
575
576impl<const N: usize> EvmCdSerialise for [u8; N] {
577 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
578 if N == 0 || N > 32 {
579 return Err(invalid_data());
580 }
581 writer.write_all(self)?;
582 const ZEROES: [u8; 32] = [0; 32];
583 writer.write_all(&ZEROES[..32 - N])
584 }
585
586 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
587 hasher.update(b"bytes").update_usize(N)
588 }
589}
590
591impl<const N: usize> EvmCdDeserialise for [u8; N] {
592 fixed_deserialise_buffer!([u8; 32]);
593
594 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
595 if N == 0 || N > 32 {
596 return Err(invalid_data());
597 }
598 let mut word = [0u8; 32];
599 reader.read_exact(&mut word)?;
600 if word[N..].iter().any(|byte| *byte != 0) {
601 return Err(invalid_data());
602 }
603 Ok(word[..N].try_into().unwrap())
604 }
605
606 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
607 hasher.update(b"bytes").update_usize(N)
608 }
609}
610
611#[derive(Debug, Clone, Copy, PartialEq, Eq)]
612pub enum EvmCdArrayError {
613 InvalidBounds,
614 TooShort,
615 TooLong,
616}
617
618pub struct EvmCdArray<T, const MIN: usize, const CAP: usize> {
619 len: usize,
620 values: [core::mem::MaybeUninit<T>; CAP],
621}
622
623impl<T, const MIN: usize, const CAP: usize> EvmCdArray<T, MIN, CAP> {
624 fn empty() -> Self {
625 Self {
626 len: 0,
627 values: [const { core::mem::MaybeUninit::uninit() }; CAP],
628 }
629 }
630
631 fn validate_len(len: usize) -> Result<(), EvmCdArrayError> {
632 if MIN > CAP {
633 return Err(EvmCdArrayError::InvalidBounds);
634 }
635 if len < MIN {
636 return Err(EvmCdArrayError::TooShort);
637 }
638 if len > CAP {
639 return Err(EvmCdArrayError::TooLong);
640 }
641 Ok(())
642 }
643
644 fn push(&mut self, value: T) {
645 debug_assert!(self.len < CAP);
646 self.values[self.len].write(value);
647 self.len += 1;
648 }
649
650 pub fn try_from_array(values: [T; CAP], len: usize) -> Result<Self, EvmCdArrayError> {
651 Self::validate_len(len)?;
652 let mut out = Self::empty();
653 for value in values.into_iter().take(len) {
654 out.push(value);
655 }
656 Ok(out)
657 }
658
659 pub fn try_from_slice(values: &[T]) -> Result<Self, EvmCdArrayError>
660 where
661 T: Clone,
662 {
663 Self::validate_len(values.len())?;
664 let mut out = Self::empty();
665 for value in values {
666 out.push(value.clone());
667 }
668 Ok(out)
669 }
670
671 pub const fn len(&self) -> usize {
672 self.len
673 }
674
675 pub const fn is_empty(&self) -> bool {
676 self.len == 0
677 }
678
679 pub const fn capacity(&self) -> usize {
680 CAP
681 }
682
683 pub fn as_slice(&self) -> &[T] {
684 unsafe { core::slice::from_raw_parts(self.values.as_ptr().cast::<T>(), self.len) }
687 }
688}
689
690impl<T, const MIN: usize, const CAP: usize> Drop for EvmCdArray<T, MIN, CAP> {
691 fn drop(&mut self) {
692 for value in &mut self.values[..self.len] {
693 unsafe { value.assume_init_drop() };
695 }
696 }
697}
698
699impl<T: Clone, const MIN: usize, const CAP: usize> Clone for EvmCdArray<T, MIN, CAP> {
700 fn clone(&self) -> Self {
701 Self::try_from_slice(self.as_slice()).expect("an existing EvmCdArray has valid bounds")
702 }
703}
704
705impl<T: core::fmt::Debug, const MIN: usize, const CAP: usize> core::fmt::Debug
706 for EvmCdArray<T, MIN, CAP>
707{
708 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
709 formatter.debug_list().entries(self.as_slice()).finish()
710 }
711}
712
713impl<T: PartialEq, const MIN: usize, const CAP: usize> PartialEq for EvmCdArray<T, MIN, CAP> {
714 fn eq(&self, other: &Self) -> bool {
715 self.as_slice() == other.as_slice()
716 }
717}
718
719impl<T: Eq, const MIN: usize, const CAP: usize> Eq for EvmCdArray<T, MIN, CAP> {}
720
721impl<T, const MIN: usize, const CAP: usize> AsRef<[T]> for EvmCdArray<T, MIN, CAP> {
722 fn as_ref(&self) -> &[T] {
723 self.as_slice()
724 }
725}
726
727impl<T, const MIN: usize, const CAP: usize> EvmCdSerialise for EvmCdArray<T, MIN, CAP>
728where
729 T: EvmCdSerialise,
730{
731 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
732 U::from_u32(32).serialise_value(writer)?;
733 self.serialise_abi_tail(writer)
734 }
735
736 fn is_abi_dynamic() -> bool {
737 true
738 }
739
740 fn abi_tail_size(&self) -> usize {
741 self.len
742 .saturating_mul(T::abi_head_size())
743 .saturating_add(32)
744 .saturating_add(self.as_slice().iter().fold(0usize, |size, value| {
745 size.saturating_add(value.abi_tail_size())
746 }))
747 }
748
749 fn serialise_abi_head<W: Write>(
750 &self,
751 tail_offset: usize,
752 writer: &mut W,
753 ) -> Result<(), Error> {
754 U::from_usize(tail_offset).serialise_value(writer)
755 }
756
757 fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
758 U::from_usize(self.len).serialise_value(writer)?;
759 let mut tail_offset = self
760 .len
761 .checked_mul(T::abi_head_size())
762 .ok_or_else(invalid_data)?;
763 for value in self.as_slice() {
764 value.serialise_abi_head(tail_offset, writer)?;
765 tail_offset = tail_offset
766 .checked_add(value.abi_tail_size())
767 .ok_or_else(invalid_data)?;
768 }
769 for value in self.as_slice() {
770 value.serialise_abi_tail(writer)?;
771 }
772 Ok(())
773 }
774
775 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
776 T::append_abi_type(hasher).update(b"[]")
777 }
778}
779
780impl<T, const MIN: usize, const CAP: usize> EvmCdDeserialise for EvmCdArray<T, MIN, CAP>
781where
782 T: EvmCdDeserialise,
783{
784 type Buffer = <<T::Buffer as EvmCdDecodeBuffer>::Kind as EvmCdBufferKind>::Buffer<(
785 [u8; 64],
786 [T::Buffer; CAP],
787 )>;
788
789 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
790 if read_usize_word(reader)? != 32 {
791 return Err(invalid_data());
792 }
793 Self::deserialise_tail(reader)
794 }
795
796 fn is_abi_dynamic() -> bool {
797 true
798 }
799
800 fn abi_tail_size(&self) -> usize {
801 self.len
802 .saturating_mul(T::abi_head_size())
803 .saturating_add(32)
804 .saturating_add(self.as_slice().iter().fold(0usize, |size, value| {
805 size.saturating_add(value.abi_tail_size())
806 }))
807 }
808
809 fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
810 Ok(EvmCdHead::Offset(read_usize_word(reader)?))
811 }
812
813 fn deserialise_abi_finish<R: Read>(
814 head: EvmCdHead<Self>,
815 expected_tail_offset: usize,
816 reader: &mut R,
817 ) -> Result<Self, Error> {
818 match head {
819 EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
820 Self::deserialise_tail(reader)
821 }
822 _ => Err(invalid_data()),
823 }
824 }
825
826 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
827 T::append_abi_type(hasher).update(b"[]")
828 }
829}
830
831impl<T, const MIN: usize, const CAP: usize> EvmCdArray<T, MIN, CAP>
832where
833 T: EvmCdDeserialise,
834{
835 fn deserialise_tail<R: Read>(reader: &mut R) -> Result<Self, Error> {
836 let len = read_usize_word(reader)?;
837 Self::validate_len(len).map_err(|_| invalid_data())?;
838 let mut out = Self::empty();
839
840 if T::is_abi_dynamic() {
841 let mut offsets = [0usize; CAP];
842 for offset in &mut offsets[..len] {
843 match T::deserialise_abi_head(reader)? {
844 EvmCdHead::Offset(value) => *offset = value,
845 EvmCdHead::Value(_) => return Err(invalid_data()),
846 }
847 }
848 let mut expected_tail_offset = len
849 .checked_mul(T::abi_head_size())
850 .ok_or_else(invalid_data)?;
851 for offset in offsets[..len].iter().copied() {
852 let value = T::deserialise_abi_finish(
853 EvmCdHead::Offset(offset),
854 expected_tail_offset,
855 reader,
856 )?;
857 expected_tail_offset = expected_tail_offset
858 .checked_add(value.abi_tail_size())
859 .ok_or_else(invalid_data)?;
860 out.push(value);
861 }
862 } else {
863 for _ in 0..len {
864 let head = T::deserialise_abi_head(reader)?;
865 out.push(T::deserialise_abi_finish(head, 0, reader)?);
866 }
867 }
868 Ok(out)
869 }
870}
871
872#[derive(Debug, Clone, Copy, PartialEq, Eq)]
873pub enum EvmCdStringError {
874 InvalidBounds,
875 TooShort,
876 TooLong,
877}
878
879#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
880pub struct EvmCdString<const MIN: usize, const CAP: usize> {
881 len: usize,
882 bytes: [u8; CAP],
883}
884
885impl<const MIN: usize, const CAP: usize> EvmCdString<MIN, CAP> {
886 pub fn try_from_str(value: &str) -> Result<Self, EvmCdStringError> {
887 if MIN > CAP {
888 return Err(EvmCdStringError::InvalidBounds);
889 }
890 if value.len() < MIN {
891 return Err(EvmCdStringError::TooShort);
892 }
893 if value.len() > CAP {
894 return Err(EvmCdStringError::TooLong);
895 }
896 let mut bytes = [0u8; CAP];
897 bytes[..value.len()].copy_from_slice(value.as_bytes());
898 Ok(Self {
899 len: value.len(),
900 bytes,
901 })
902 }
903
904 pub const fn len(&self) -> usize {
905 self.len
906 }
907
908 pub const fn is_empty(&self) -> bool {
909 self.len == 0
910 }
911
912 pub const fn capacity(&self) -> usize {
913 CAP
914 }
915
916 pub fn as_bytes(&self) -> &[u8] {
917 &self.bytes[..self.len]
918 }
919
920 pub fn as_str(&self) -> &str {
921 unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
924 }
925}
926
927impl<const MIN: usize, const CAP: usize> TryFrom<&str> for EvmCdString<MIN, CAP> {
928 type Error = EvmCdStringError;
929
930 fn try_from(value: &str) -> Result<Self, Self::Error> {
931 Self::try_from_str(value)
932 }
933}
934
935impl<const MIN: usize, const CAP: usize> AsRef<str> for EvmCdString<MIN, CAP> {
936 fn as_ref(&self) -> &str {
937 self.as_str()
938 }
939}
940
941impl<const MIN: usize, const CAP: usize> AsRef<[u8]> for EvmCdString<MIN, CAP> {
942 fn as_ref(&self) -> &[u8] {
943 self.as_bytes()
944 }
945}
946
947impl<const MIN: usize, const CAP: usize> core::borrow::Borrow<str> for EvmCdString<MIN, CAP> {
948 fn borrow(&self) -> &str {
949 self.as_str()
950 }
951}
952
953impl<const MIN: usize, const CAP: usize> core::fmt::Display for EvmCdString<MIN, CAP> {
954 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
955 formatter.write_str(self.as_str())
956 }
957}
958
959impl<const MIN: usize, const CAP: usize> core::fmt::Debug for EvmCdString<MIN, CAP> {
960 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
961 core::fmt::Debug::fmt(self.as_str(), formatter)
962 }
963}
964
965impl<const MIN: usize, const CAP: usize> core::str::FromStr for EvmCdString<MIN, CAP> {
966 type Err = EvmCdStringError;
967
968 fn from_str(value: &str) -> Result<Self, Self::Err> {
969 Self::try_from_str(value)
970 }
971}
972
973impl<const MIN: usize, const CAP: usize> EvmCdSerialise for EvmCdString<MIN, CAP> {
974 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
975 write_dynamic_bytes(self.as_bytes(), writer)
976 }
977
978 fn is_abi_dynamic() -> bool {
979 true
980 }
981
982 fn abi_tail_size(&self) -> usize {
983 dynamic_tail_size(self.len)
984 }
985
986 fn serialise_abi_head<W: Write>(
987 &self,
988 tail_offset: usize,
989 writer: &mut W,
990 ) -> Result<(), Error> {
991 U::from_usize(tail_offset).serialise_value(writer)
992 }
993
994 fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
995 write_dynamic_tail(self.as_bytes(), writer)
996 }
997
998 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
999 hasher.update(b"string")
1000 }
1001}
1002
1003impl<const MIN: usize, const CAP: usize> EvmCdDeserialise for EvmCdString<MIN, CAP> {
1004 type Buffer = EvmCdBuffer<([u8; 64], [u8; CAP], [u8; 31])>;
1005
1006 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1007 if MIN > CAP {
1008 return Err(invalid_data());
1009 }
1010 let (bytes, len) = read_dynamic_bytes::<CAP, _>(reader)?;
1011 if len < MIN || core::str::from_utf8(&bytes[..len]).is_err() {
1012 return Err(invalid_data());
1013 }
1014 Ok(Self { len, bytes })
1015 }
1016
1017 fn is_abi_dynamic() -> bool {
1018 true
1019 }
1020
1021 fn abi_tail_size(&self) -> usize {
1022 dynamic_tail_size(self.len)
1023 }
1024
1025 fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1026 Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1027 }
1028
1029 fn deserialise_abi_finish<R: Read>(
1030 head: EvmCdHead<Self>,
1031 expected_tail_offset: usize,
1032 reader: &mut R,
1033 ) -> Result<Self, Error> {
1034 match head {
1035 EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1036 if MIN > CAP {
1037 return Err(invalid_data());
1038 }
1039 let (bytes, len) = read_dynamic_tail::<CAP, _>(reader)?;
1040 if len < MIN || core::str::from_utf8(&bytes[..len]).is_err() {
1041 return Err(invalid_data());
1042 }
1043 Ok(Self { len, bytes })
1044 }
1045 _ => Err(invalid_data()),
1046 }
1047 }
1048
1049 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1050 hasher.update(b"string")
1051 }
1052}
1053
1054#[cfg(feature = "alloc")]
1055impl<const MIN: usize, const CAP: usize> From<EvmCdString<MIN, CAP>> for String {
1056 fn from(value: EvmCdString<MIN, CAP>) -> Self {
1057 String::from(value.as_str())
1058 }
1059}
1060
1061#[cfg(feature = "alloc")]
1062fn vec_is_bytes<T: 'static>() -> bool {
1063 core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>()
1064}
1065
1066#[cfg(feature = "alloc")]
1067fn vec_as_bytes<T: 'static>(values: &[T]) -> &[u8] {
1068 debug_assert!(vec_is_bytes::<T>());
1069 unsafe { core::slice::from_raw_parts(values.as_ptr().cast::<u8>(), values.len()) }
1071}
1072
1073#[cfg(feature = "alloc")]
1074impl<T> EvmCdSerialise for Vec<T>
1075where
1076 T: EvmCdSerialise + 'static,
1077{
1078 fn serialise<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1079 U::from_u32(32).serialise_value(writer)?;
1080 self.serialise_abi_tail(writer)
1081 }
1082
1083 fn is_abi_dynamic() -> bool {
1084 true
1085 }
1086
1087 fn abi_tail_size(&self) -> usize {
1088 if vec_is_bytes::<T>() {
1089 dynamic_tail_size(self.len())
1090 } else {
1091 self.len()
1092 .saturating_mul(T::abi_head_size())
1093 .saturating_add(32)
1094 .saturating_add(self.iter().fold(0usize, |size, value| {
1095 size.saturating_add(value.abi_tail_size())
1096 }))
1097 }
1098 }
1099
1100 fn serialise_abi_head<W: Write>(
1101 &self,
1102 tail_offset: usize,
1103 writer: &mut W,
1104 ) -> Result<(), Error> {
1105 U::from_usize(tail_offset).serialise_value(writer)
1106 }
1107
1108 fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1109 if vec_is_bytes::<T>() {
1110 return write_dynamic_tail(vec_as_bytes(self), writer);
1111 }
1112
1113 U::from_usize(self.len()).serialise_value(writer)?;
1114 let mut tail_offset = self
1115 .len()
1116 .checked_mul(T::abi_head_size())
1117 .ok_or_else(invalid_data)?;
1118 for value in self {
1119 value.serialise_abi_head(tail_offset, writer)?;
1120 tail_offset = tail_offset
1121 .checked_add(value.abi_tail_size())
1122 .ok_or_else(invalid_data)?;
1123 }
1124 for value in self {
1125 value.serialise_abi_tail(writer)?;
1126 }
1127 Ok(())
1128 }
1129
1130 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1131 if vec_is_bytes::<T>() {
1132 hasher.update(b"bytes")
1133 } else {
1134 T::append_abi_type(hasher).update(b"[]")
1135 }
1136 }
1137}
1138
1139#[cfg(feature = "alloc")]
1140const MAX_ALLOC_DESERIALISE_LEN: usize = 16 * 1024 * 1024;
1141
1142#[cfg(feature = "alloc")]
1143fn read_vec_bytes_tail<R: Read>(reader: &mut R) -> Result<Vec<u8>, Error> {
1144 let len = read_usize_word(reader)?;
1145 if len > MAX_ALLOC_DESERIALISE_LEN {
1146 return Err(invalid_data());
1147 }
1148 let mut out = Vec::new();
1149 out.try_reserve_exact(len).map_err(|_| invalid_data())?;
1150 out.resize(len, 0);
1151 reader.read_exact(&mut out)?;
1152 let padding = (32 - len % 32) % 32;
1153 let mut padding_bytes = [0u8; 31];
1154 reader.read_exact(&mut padding_bytes[..padding])?;
1155 if padding_bytes[..padding].iter().any(|byte| *byte != 0) {
1156 return Err(invalid_data());
1157 }
1158 Ok(out)
1159}
1160
1161#[cfg(feature = "alloc")]
1162fn bytes_into_vec<T: 'static>(bytes: Vec<u8>) -> Vec<T> {
1163 debug_assert!(vec_is_bytes::<T>());
1164 let mut bytes = core::mem::ManuallyDrop::new(bytes);
1165 unsafe {
1167 Vec::from_raw_parts(
1168 bytes.as_mut_ptr().cast::<T>(),
1169 bytes.len(),
1170 bytes.capacity(),
1171 )
1172 }
1173}
1174
1175#[cfg(feature = "alloc")]
1176fn validate_vec_array_len<T: EvmCdDeserialise>(len: usize) -> Result<(), Error> {
1177 let head_bytes = len
1178 .checked_mul(T::abi_head_size())
1179 .ok_or_else(invalid_data)?;
1180 let value_bytes = len
1181 .checked_mul(core::mem::size_of::<T>())
1182 .ok_or_else(invalid_data)?;
1183 let offset_bytes = if T::is_abi_dynamic() {
1184 len.checked_mul(core::mem::size_of::<usize>())
1185 .ok_or_else(invalid_data)?
1186 } else {
1187 0
1188 };
1189 if head_bytes > MAX_ALLOC_DESERIALISE_LEN
1190 || value_bytes > MAX_ALLOC_DESERIALISE_LEN
1191 || offset_bytes > MAX_ALLOC_DESERIALISE_LEN
1192 {
1193 return Err(invalid_data());
1194 }
1195 Ok(())
1196}
1197
1198#[cfg(feature = "alloc")]
1199fn read_vec_array_tail<T, R>(reader: &mut R) -> Result<Vec<T>, Error>
1200where
1201 T: EvmCdDeserialise + 'static,
1202 R: Read,
1203{
1204 let len = read_usize_word(reader)?;
1205 validate_vec_array_len::<T>(len)?;
1206
1207 let mut out = Vec::new();
1208 out.try_reserve_exact(len).map_err(|_| invalid_data())?;
1209 if T::is_abi_dynamic() {
1210 let mut offsets = Vec::new();
1211 offsets.try_reserve_exact(len).map_err(|_| invalid_data())?;
1212 for _ in 0..len {
1213 match T::deserialise_abi_head(reader)? {
1214 EvmCdHead::Offset(offset) => offsets.push(offset),
1215 EvmCdHead::Value(_) => return Err(invalid_data()),
1216 }
1217 }
1218 let mut expected_tail_offset = len
1219 .checked_mul(T::abi_head_size())
1220 .ok_or_else(invalid_data)?;
1221 for offset in offsets {
1222 let value =
1223 T::deserialise_abi_finish(EvmCdHead::Offset(offset), expected_tail_offset, reader)?;
1224 expected_tail_offset = expected_tail_offset
1225 .checked_add(value.abi_tail_size())
1226 .ok_or_else(invalid_data)?;
1227 out.push(value);
1228 }
1229 } else {
1230 for _ in 0..len {
1231 let head = T::deserialise_abi_head(reader)?;
1232 out.push(T::deserialise_abi_finish(head, 0, reader)?);
1233 }
1234 }
1235 Ok(out)
1236}
1237
1238#[cfg(feature = "alloc")]
1239fn read_vec_tail<T, R>(reader: &mut R) -> Result<Vec<T>, Error>
1240where
1241 T: EvmCdDeserialise + 'static,
1242 R: Read,
1243{
1244 if vec_is_bytes::<T>() {
1245 read_vec_bytes_tail(reader).map(bytes_into_vec)
1246 } else {
1247 read_vec_array_tail(reader)
1248 }
1249}
1250
1251#[cfg(feature = "alloc")]
1252impl<T> EvmCdDeserialise for Vec<T>
1253where
1254 T: EvmCdDeserialise + 'static,
1255{
1256 type Buffer = EvmCdDynamicBuffer<()>;
1257
1258 fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1259 if read_usize_word(reader)? != 32 {
1260 return Err(invalid_data());
1261 }
1262 read_vec_tail(reader)
1263 }
1264
1265 fn is_abi_dynamic() -> bool {
1266 true
1267 }
1268
1269 fn abi_tail_size(&self) -> usize {
1270 if vec_is_bytes::<T>() {
1271 dynamic_tail_size(self.len())
1272 } else {
1273 self.len()
1274 .saturating_mul(T::abi_head_size())
1275 .saturating_add(32)
1276 .saturating_add(self.iter().fold(0usize, |size, value| {
1277 size.saturating_add(value.abi_tail_size())
1278 }))
1279 }
1280 }
1281
1282 fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1283 Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1284 }
1285
1286 fn deserialise_abi_finish<R: Read>(
1287 head: EvmCdHead<Self>,
1288 expected_tail_offset: usize,
1289 reader: &mut R,
1290 ) -> Result<Self, Error> {
1291 match head {
1292 EvmCdHead::Offset(offset) if offset == expected_tail_offset => read_vec_tail(reader),
1293 _ => Err(invalid_data()),
1294 }
1295 }
1296
1297 fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1298 if vec_is_bytes::<T>() {
1299 hasher.update(b"bytes")
1300 } else {
1301 T::append_abi_type(hasher).update(b"[]")
1302 }
1303 }
1304}