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