Skip to main content

bobcat_cd/
serialisation.rs

1use bobcat_maths::{I, 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    fn serialise_to_array<const N: usize>(&self) -> Result<[u8; N], Error> {
227        let mut output = [0; N];
228        let mut writer = output.as_mut_slice();
229        self.serialise_writer(&mut writer)?;
230        if !writer.is_empty() {
231            return Err(invalid_data());
232        }
233        Ok(output)
234    }
235
236    #[cfg(feature = "alloc")]
237    fn serialise_to_vec(&self) -> Result<Vec<u8>, Error> {
238        let mut output = Vec::new();
239        self.serialise(&mut output)?;
240        Ok(output)
241    }
242
243    #[doc(hidden)]
244    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error>;
245
246    #[doc(hidden)]
247    fn serialise_value<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
248        self.serialise_writer(writer)
249    }
250
251    #[doc(hidden)]
252    fn is_abi_dynamic() -> bool {
253        false
254    }
255
256    #[doc(hidden)]
257    fn abi_head_size() -> usize {
258        32
259    }
260
261    #[doc(hidden)]
262    fn abi_tail_size(&self) -> usize {
263        0
264    }
265
266    #[doc(hidden)]
267    fn serialise_abi_head<W: Write>(
268        &self,
269        _tail_offset: usize,
270        writer: &mut W,
271    ) -> Result<(), Error> {
272        self.serialise_value(writer)
273    }
274
275    #[doc(hidden)]
276    fn serialise_abi_tail<W: Write>(&self, _writer: &mut W) -> Result<(), Error> {
277        Ok(())
278    }
279
280    #[doc(hidden)]
281    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher;
282}
283
284#[doc(hidden)]
285pub enum EvmCdHead<T> {
286    Value(T),
287    Offset(usize),
288}
289
290#[doc(hidden)]
291pub struct EvmCdStaticBufferKind;
292
293#[cfg(feature = "alloc")]
294#[doc(hidden)]
295pub struct EvmCdDynamicBufferKind;
296
297#[doc(hidden)]
298pub trait EvmCdBufferKind {
299    type Buffer<S>: EvmCdDecodeBuffer;
300    type Combined<Rhs: EvmCdBufferKind>: EvmCdBufferKind;
301}
302
303impl EvmCdBufferKind for EvmCdStaticBufferKind {
304    type Buffer<S> = EvmCdBuffer<S>;
305    type Combined<Rhs: EvmCdBufferKind> = Rhs;
306}
307
308#[cfg(feature = "alloc")]
309impl EvmCdBufferKind for EvmCdDynamicBufferKind {
310    type Buffer<S> = EvmCdDynamicBuffer<S>;
311    type Combined<Rhs: EvmCdBufferKind> = EvmCdDynamicBufferKind;
312}
313
314#[doc(hidden)]
315pub trait EvmCdDecodeBuffer: AsRef<[u8]> + AsMut<[u8]> + Sized {
316    type Kind: EvmCdBufferKind;
317
318    fn new(len: usize) -> Result<Self, Error>;
319}
320
321#[doc(hidden)]
322pub struct EvmCdBuffer<S> {
323    storage: core::mem::MaybeUninit<S>,
324}
325
326impl<S> EvmCdDecodeBuffer for EvmCdBuffer<S> {
327    type Kind = EvmCdStaticBufferKind;
328
329    fn new(len: usize) -> Result<Self, Error> {
330        if len > size_of::<S>() {
331            return Err(invalid_data());
332        }
333        let mut storage = core::mem::MaybeUninit::<S>::uninit();
334        // SAFETY: the storage remains wrapped in MaybeUninit and is only exposed as bytes.
335        // Zeroing every byte makes the complete u8 slice valid without constructing an S.
336        unsafe {
337            storage
338                .as_mut_ptr()
339                .cast::<u8>()
340                .write_bytes(0, size_of::<S>())
341        };
342        Ok(Self { storage })
343    }
344}
345
346impl<S> AsRef<[u8]> for EvmCdBuffer<S> {
347    fn as_ref(&self) -> &[u8] {
348        // SAFETY: new() zero-initializes every byte before constructing Self.
349        unsafe { core::slice::from_raw_parts(self.storage.as_ptr().cast::<u8>(), size_of::<S>()) }
350    }
351}
352
353impl<S> AsMut<[u8]> for EvmCdBuffer<S> {
354    fn as_mut(&mut self) -> &mut [u8] {
355        // SAFETY: new() zero-initializes every byte before constructing Self.
356        unsafe {
357            core::slice::from_raw_parts_mut(self.storage.as_mut_ptr().cast::<u8>(), size_of::<S>())
358        }
359    }
360}
361
362#[cfg(feature = "alloc")]
363#[doc(hidden)]
364pub struct EvmCdDynamicBuffer<S>(pub Vec<u8>, pub core::marker::PhantomData<S>);
365
366#[cfg(feature = "alloc")]
367impl<S> EvmCdDecodeBuffer for EvmCdDynamicBuffer<S> {
368    type Kind = EvmCdDynamicBufferKind;
369
370    fn new(len: usize) -> Result<Self, Error> {
371        if len > MAX_ALLOC_DESERIALISE_LEN {
372            return Err(invalid_data());
373        }
374        let mut bytes = Vec::new();
375        bytes.try_reserve_exact(len).map_err(|_| invalid_data())?;
376        bytes.resize(len, 0);
377        Ok(Self(bytes, core::marker::PhantomData))
378    }
379}
380
381#[cfg(feature = "alloc")]
382impl<S> AsRef<[u8]> for EvmCdDynamicBuffer<S> {
383    fn as_ref(&self) -> &[u8] {
384        &self.0
385    }
386}
387
388#[cfg(feature = "alloc")]
389impl<S> AsMut<[u8]> for EvmCdDynamicBuffer<S> {
390    fn as_mut(&mut self) -> &mut [u8] {
391        &mut self.0
392    }
393}
394
395pub trait EvmCdDeserialise: Sized {
396    type Buffer: EvmCdDecodeBuffer;
397
398    fn new_buffer(len: usize) -> Result<Self::Buffer, Error> {
399        Self::Buffer::new(len)
400    }
401
402    fn deserialise<B>(bytes: &B) -> Result<Self, Error>
403    where
404        B: AsRef<[u8]> + ?Sized,
405    {
406        let mut reader = bytes.as_ref();
407        Self::deserialise_reader(&mut reader)
408    }
409
410    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error>;
411
412    #[doc(hidden)]
413    fn deserialise_value<R: Read>(reader: &mut R) -> Result<Self, Error> {
414        Self::deserialise_reader(reader)
415    }
416
417    #[doc(hidden)]
418    fn is_abi_dynamic() -> bool {
419        false
420    }
421
422    #[doc(hidden)]
423    fn abi_head_size() -> usize {
424        32
425    }
426
427    #[doc(hidden)]
428    fn abi_tail_size(&self) -> usize {
429        0
430    }
431
432    #[doc(hidden)]
433    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
434        Ok(EvmCdHead::Value(Self::deserialise_value(reader)?))
435    }
436
437    #[doc(hidden)]
438    fn deserialise_abi_finish<R: Read>(
439        head: EvmCdHead<Self>,
440        _expected_tail_offset: usize,
441        _reader: &mut R,
442    ) -> Result<Self, Error> {
443        match head {
444            EvmCdHead::Value(value) => Ok(value),
445            EvmCdHead::Offset(_) => Err(invalid_data()),
446        }
447    }
448
449    #[doc(hidden)]
450    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher;
451}
452
453#[cfg(not(feature = "std"))]
454pub fn invalid_data() -> Error {
455    Error::InvalidData
456}
457
458#[cfg(feature = "std")]
459pub fn invalid_data() -> Error {
460    Error::new(std::io::ErrorKind::InvalidData, "invalid EVM calldata")
461}
462
463fn read_usize_word<R: Read>(reader: &mut R) -> Result<usize, Error> {
464    let mut word = [0u8; 32];
465    reader.read_exact(&mut word)?;
466    if word[..32 - size_of::<usize>()]
467        .iter()
468        .any(|byte| *byte != 0)
469    {
470        return Err(invalid_data());
471    }
472    Ok(usize::from_be_bytes(
473        word[32 - size_of::<usize>()..].try_into().unwrap(),
474    ))
475}
476
477fn write_dynamic_tail<W: Write>(bytes: &[u8], writer: &mut W) -> Result<(), Error> {
478    writer.write_all(&U::from_usize(bytes.len()).0)?;
479    writer.write_all(bytes)?;
480    const ZEROES: [u8; 31] = [0; 31];
481    let padding = (32 - bytes.len() % 32) % 32;
482    writer.write_all(&ZEROES[..padding])
483}
484
485fn write_dynamic_bytes<W: Write>(bytes: &[u8], writer: &mut W) -> Result<(), Error> {
486    writer.write_all(&U::from_u32(32).0)?;
487    write_dynamic_tail(bytes, writer)
488}
489
490fn dynamic_tail_size(len: usize) -> usize {
491    32 + len + (32 - len % 32) % 32
492}
493
494fn read_dynamic_tail<const CAP: usize, R: Read>(
495    reader: &mut R,
496) -> Result<([u8; CAP], usize), Error> {
497    let len = read_usize_word(reader)?;
498    if len > CAP {
499        return Err(invalid_data());
500    }
501    let mut bytes = [0u8; CAP];
502    reader.read_exact(&mut bytes[..len])?;
503    let padding = (32 - len % 32) % 32;
504    let mut padding_bytes = [0u8; 31];
505    reader.read_exact(&mut padding_bytes[..padding])?;
506    if padding_bytes[..padding].iter().any(|byte| *byte != 0) {
507        return Err(invalid_data());
508    }
509    Ok((bytes, len))
510}
511
512fn read_dynamic_bytes<const CAP: usize, R: Read>(
513    reader: &mut R,
514) -> Result<([u8; CAP], usize), Error> {
515    if read_usize_word(reader)? != 32 {
516        return Err(invalid_data());
517    }
518    read_dynamic_tail(reader)
519}
520
521macro_rules! fixed_deserialise_buffer {
522    ($storage:ty) => {
523        type Buffer = EvmCdBuffer<$storage>;
524    };
525}
526
527impl EvmCdSerialise for U {
528    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
529        writer.write_all(&self.0)
530    }
531
532    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
533        hasher.update(b"uint256")
534    }
535}
536
537impl EvmCdDeserialise for U {
538    fixed_deserialise_buffer!([u8; 32]);
539
540    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
541        let mut buf = [0u8; 32];
542        reader.read_exact(&mut buf)?;
543        Ok(U(buf))
544    }
545
546    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
547        hasher.update(b"uint256")
548    }
549}
550
551impl EvmCdSerialise for bool {
552    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
553        u8::from(*self).serialise_value(writer)
554    }
555
556    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
557        hasher.update(b"bool")
558    }
559}
560
561impl EvmCdDeserialise for bool {
562    fixed_deserialise_buffer!([u8; 32]);
563
564    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
565        match u8::deserialise_reader(reader)? {
566            0 => Ok(false),
567            1 => Ok(true),
568            _ => Err(invalid_data()),
569        }
570    }
571
572    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
573        hasher.update(b"bool")
574    }
575}
576
577macro_rules! for_ints {
578    ($($ty:ty => $abi:literal),+ $(,)?) => {
579        $(
580            impl EvmCdSerialise for $ty {
581                fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
582                    writer.write_all(&[0u8; 32 - size_of::<$ty>()])?;
583                    writer.write_all(&self.to_be_bytes())
584                }
585
586                fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
587                    hasher.update($abi)
588                }
589            }
590
591            impl EvmCdDeserialise for $ty {
592                fixed_deserialise_buffer!([u8; 32]);
593
594                fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
595                    let U(word) = U::deserialise_reader(reader)?;
596                    if word[..32 - size_of::<$ty>()].iter().any(|byte| *byte != 0) {
597                        return Err(invalid_data());
598                    }
599                    Ok(<$ty>::from_be_bytes(
600                        word[32 - size_of::<$ty>()..].try_into().unwrap(),
601                    ))
602                }
603
604                fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
605                    hasher.update($abi)
606                }
607            }
608        )+
609    };
610}
611
612for_ints! {
613    u8 => b"uint8",
614    u16 => b"uint16",
615    u32 => b"uint32",
616    u64 => b"uint64",
617    u128 => b"uint128",
618}
619
620macro_rules! for_signed_ints {
621    ($($ty:ty => $abi:literal),+ $(,)?) => {
622        $(
623            impl EvmCdSerialise for $ty {
624                fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
625                    let extension = if self.is_negative() { 0xff } else { 0 };
626                    writer.write_all(&[extension; 32 - size_of::<$ty>()])?;
627                    writer.write_all(&self.to_be_bytes())
628                }
629
630                fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
631                    hasher.update($abi)
632                }
633            }
634
635            impl EvmCdDeserialise for $ty {
636                fixed_deserialise_buffer!([u8; 32]);
637
638                fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
639                    let mut word = [0u8; 32];
640                    reader.read_exact(&mut word)?;
641                    let value_start = 32 - size_of::<$ty>();
642                    let extension = if word[value_start] & 0x80 == 0 { 0 } else { 0xff };
643                    if word[..value_start].iter().any(|byte| *byte != extension) {
644                        return Err(invalid_data());
645                    }
646                    Ok(<$ty>::from_be_bytes(word[value_start..].try_into().unwrap()))
647                }
648
649                fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
650                    hasher.update($abi)
651                }
652            }
653        )+
654    };
655}
656
657for_signed_ints! {
658    i8 => b"int8",
659    i16 => b"int16",
660    i32 => b"int32",
661    i64 => b"int64",
662    i128 => b"int128",
663}
664
665impl EvmCdSerialise for usize {
666    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
667        <u32 as EvmCdSerialise>::serialise_value(
668            &u32::try_from(*self).map_err(|_| invalid_data())?,
669            writer,
670        )
671    }
672
673    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
674        hasher.update(b"uint32")
675    }
676}
677
678impl EvmCdDeserialise for usize {
679    fixed_deserialise_buffer!([u8; 32]);
680
681    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
682        Ok(u32::deserialise_reader(reader)? as usize)
683    }
684
685    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
686        hasher.update(b"uint32")
687    }
688}
689
690macro_rules! evm_cd_uint {
691    ($name:ident, $bits:literal, $bytes:literal) => {
692        #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
693        pub struct $name(pub [u8; $bytes]);
694
695        impl $name {
696            pub const fn new(bytes: [u8; $bytes]) -> Self {
697                Self(bytes)
698            }
699
700            pub const fn into_array(self) -> [u8; $bytes] {
701                self.0
702            }
703
704            pub const fn as_array(&self) -> &[u8; $bytes] {
705                &self.0
706            }
707        }
708
709        impl From<[u8; $bytes]> for $name {
710            fn from(bytes: [u8; $bytes]) -> Self {
711                Self::new(bytes)
712            }
713        }
714
715        impl From<$name> for [u8; $bytes] {
716            fn from(value: $name) -> Self {
717                value.into_array()
718            }
719        }
720
721        impl From<$name> for U {
722            fn from(value: $name) -> Self {
723                let mut word = [0u8; 32];
724                word[32 - $bytes..].copy_from_slice(value.as_array());
725                Self::from(word)
726            }
727        }
728
729        impl From<U> for $name {
730            fn from(value: U) -> Self {
731                let word: [u8; 32] = value.into();
732                Self::new(word[32 - $bytes..].try_into().unwrap())
733            }
734        }
735
736        impl AsRef<[u8; $bytes]> for $name {
737            fn as_ref(&self) -> &[u8; $bytes] {
738                self.as_array()
739            }
740        }
741
742        impl AsRef<[u8]> for $name {
743            fn as_ref(&self) -> &[u8] {
744                self.as_array()
745            }
746        }
747
748        impl EvmCdSerialise for $name {
749            fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
750                writer.write_all(&[0; 32 - $bytes])?;
751                writer.write_all(&self.0)
752            }
753
754            fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
755                hasher.update(b"uint").update_usize($bits)
756            }
757        }
758
759        impl EvmCdDeserialise for $name {
760            fixed_deserialise_buffer!([u8; 32]);
761
762            fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
763                let mut word = [0u8; 32];
764                reader.read_exact(&mut word)?;
765                if word[..32 - $bytes].iter().any(|byte| *byte != 0) {
766                    return Err(invalid_data());
767                }
768                Ok(Self(word[32 - $bytes..].try_into().unwrap()))
769            }
770
771            fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
772                hasher.update(b"uint").update_usize($bits)
773            }
774        }
775    };
776}
777
778macro_rules! evm_cd_int {
779    ($name:ident, $bits:literal, $bytes:literal) => {
780        #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
781        pub struct $name(pub [u8; $bytes]);
782
783        impl $name {
784            pub const fn new(bytes: [u8; $bytes]) -> Self {
785                Self(bytes)
786            }
787
788            pub const fn into_array(self) -> [u8; $bytes] {
789                self.0
790            }
791
792            pub const fn as_array(&self) -> &[u8; $bytes] {
793                &self.0
794            }
795        }
796
797        impl From<[u8; $bytes]> for $name {
798            fn from(bytes: [u8; $bytes]) -> Self {
799                Self::new(bytes)
800            }
801        }
802
803        impl From<$name> for [u8; $bytes] {
804            fn from(value: $name) -> Self {
805                value.into_array()
806            }
807        }
808
809        impl From<$name> for I {
810            fn from(value: $name) -> Self {
811                let extension = if value.0[0] & 0x80 == 0 { 0 } else { 0xff };
812                let mut word = [extension; 32];
813                word[32 - $bytes..].copy_from_slice(value.as_array());
814                Self::from(word)
815            }
816        }
817
818        impl From<I> for $name {
819            fn from(value: I) -> Self {
820                let word: [u8; 32] = value.into();
821                Self::new(word[32 - $bytes..].try_into().unwrap())
822            }
823        }
824
825        impl AsRef<[u8; $bytes]> for $name {
826            fn as_ref(&self) -> &[u8; $bytes] {
827                self.as_array()
828            }
829        }
830
831        impl AsRef<[u8]> for $name {
832            fn as_ref(&self) -> &[u8] {
833                self.as_array()
834            }
835        }
836
837        impl EvmCdSerialise for $name {
838            fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
839                let extension = if self.0[0] & 0x80 == 0 { 0 } else { 0xff };
840                writer.write_all(&[extension; 32 - $bytes])?;
841                writer.write_all(&self.0)
842            }
843
844            fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
845                hasher.update(b"int").update_usize($bits)
846            }
847        }
848
849        impl EvmCdDeserialise for $name {
850            fixed_deserialise_buffer!([u8; 32]);
851
852            fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
853                let mut word = [0u8; 32];
854                reader.read_exact(&mut word)?;
855                let extension = if word[32 - $bytes] & 0x80 == 0 {
856                    0
857                } else {
858                    0xff
859                };
860                if word[..32 - $bytes].iter().any(|byte| *byte != extension) {
861                    return Err(invalid_data());
862                }
863                Ok(Self(word[32 - $bytes..].try_into().unwrap()))
864            }
865
866            fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
867                hasher.update(b"int").update_usize($bits)
868            }
869        }
870    };
871}
872
873macro_rules! evm_cd_integer_range {
874    ($uint_macro:ident, $int_macro:ident) => {
875        $uint_macro!(EvmCdU24, 24, 3);
876        $int_macro!(EvmCdI24, 24, 3);
877        $uint_macro!(EvmCdU40, 40, 5);
878        $int_macro!(EvmCdI40, 40, 5);
879        $uint_macro!(EvmCdU48, 48, 6);
880        $int_macro!(EvmCdI48, 48, 6);
881        $uint_macro!(EvmCdU56, 56, 7);
882        $int_macro!(EvmCdI56, 56, 7);
883        $uint_macro!(EvmCdU72, 72, 9);
884        $int_macro!(EvmCdI72, 72, 9);
885        $uint_macro!(EvmCdU80, 80, 10);
886        $int_macro!(EvmCdI80, 80, 10);
887        $uint_macro!(EvmCdU88, 88, 11);
888        $int_macro!(EvmCdI88, 88, 11);
889        $uint_macro!(EvmCdU96, 96, 12);
890        $int_macro!(EvmCdI96, 96, 12);
891        $uint_macro!(EvmCdU104, 104, 13);
892        $int_macro!(EvmCdI104, 104, 13);
893        $uint_macro!(EvmCdU112, 112, 14);
894        $int_macro!(EvmCdI112, 112, 14);
895        $uint_macro!(EvmCdU120, 120, 15);
896        $int_macro!(EvmCdI120, 120, 15);
897        $uint_macro!(EvmCdU136, 136, 17);
898        $int_macro!(EvmCdI136, 136, 17);
899        $uint_macro!(EvmCdU144, 144, 18);
900        $int_macro!(EvmCdI144, 144, 18);
901        $uint_macro!(EvmCdU152, 152, 19);
902        $int_macro!(EvmCdI152, 152, 19);
903        $uint_macro!(EvmCdU160, 160, 20);
904        $int_macro!(EvmCdI160, 160, 20);
905        $uint_macro!(EvmCdU168, 168, 21);
906        $int_macro!(EvmCdI168, 168, 21);
907        $uint_macro!(EvmCdU176, 176, 22);
908        $int_macro!(EvmCdI176, 176, 22);
909        $uint_macro!(EvmCdU184, 184, 23);
910        $int_macro!(EvmCdI184, 184, 23);
911        $uint_macro!(EvmCdU192, 192, 24);
912        $int_macro!(EvmCdI192, 192, 24);
913        $uint_macro!(EvmCdU200, 200, 25);
914        $int_macro!(EvmCdI200, 200, 25);
915        $uint_macro!(EvmCdU208, 208, 26);
916        $int_macro!(EvmCdI208, 208, 26);
917        $uint_macro!(EvmCdU216, 216, 27);
918        $int_macro!(EvmCdI216, 216, 27);
919        $uint_macro!(EvmCdU224, 224, 28);
920        $int_macro!(EvmCdI224, 224, 28);
921        $uint_macro!(EvmCdU232, 232, 29);
922        $int_macro!(EvmCdI232, 232, 29);
923        $uint_macro!(EvmCdU240, 240, 30);
924        $int_macro!(EvmCdI240, 240, 30);
925        $uint_macro!(EvmCdU248, 248, 31);
926        $int_macro!(EvmCdI248, 248, 31);
927        $uint_macro!(EvmCdU256, 256, 32);
928        $int_macro!(EvmCdI256, 256, 32);
929    };
930}
931
932evm_cd_integer_range!(evm_cd_uint, evm_cd_int);
933
934#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
935pub struct EvmCdAddress(pub [u8; 20]);
936
937impl EvmCdAddress {
938    pub const fn new(bytes: [u8; 20]) -> Self {
939        Self(bytes)
940    }
941
942    pub const fn into_array(self) -> [u8; 20] {
943        self.0
944    }
945
946    pub const fn as_array(&self) -> &[u8; 20] {
947        &self.0
948    }
949}
950
951impl From<[u8; 20]> for EvmCdAddress {
952    fn from(bytes: [u8; 20]) -> Self {
953        Self::new(bytes)
954    }
955}
956
957impl From<EvmCdAddress> for [u8; 20] {
958    fn from(address: EvmCdAddress) -> Self {
959        address.into_array()
960    }
961}
962
963impl AsRef<[u8; 20]> for EvmCdAddress {
964    fn as_ref(&self) -> &[u8; 20] {
965        self.as_array()
966    }
967}
968
969impl AsRef<[u8]> for EvmCdAddress {
970    fn as_ref(&self) -> &[u8] {
971        self.as_array()
972    }
973}
974
975impl EvmCdSerialise for EvmCdAddress {
976    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
977        writer.write_all(&[0; 12])?;
978        writer.write_all(&self.0)
979    }
980
981    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
982        hasher.update(b"address")
983    }
984}
985
986impl EvmCdDeserialise for EvmCdAddress {
987    fixed_deserialise_buffer!([u8; 32]);
988
989    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
990        let mut word = [0u8; 32];
991        reader.read_exact(&mut word)?;
992        if word[..12].iter().any(|byte| *byte != 0) {
993            return Err(invalid_data());
994        }
995        Ok(Self(word[12..].try_into().unwrap()))
996    }
997
998    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
999        hasher.update(b"address")
1000    }
1001}
1002
1003impl<const N: usize> EvmCdSerialise for [u8; N] {
1004    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1005        if N == 0 || N > 32 {
1006            return Err(invalid_data());
1007        }
1008        writer.write_all(self)?;
1009        const ZEROES: [u8; 32] = [0; 32];
1010        writer.write_all(&ZEROES[..32 - N])
1011    }
1012
1013    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1014        hasher.update(b"bytes").update_usize(N)
1015    }
1016}
1017
1018impl<const N: usize> EvmCdDeserialise for [u8; N] {
1019    fixed_deserialise_buffer!([u8; 32]);
1020
1021    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1022        if N == 0 || N > 32 {
1023            return Err(invalid_data());
1024        }
1025        let mut word = [0u8; 32];
1026        reader.read_exact(&mut word)?;
1027        if word[N..].iter().any(|byte| *byte != 0) {
1028            return Err(invalid_data());
1029        }
1030        Ok(word[..N].try_into().unwrap())
1031    }
1032
1033    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1034        hasher.update(b"bytes").update_usize(N)
1035    }
1036}
1037
1038#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1039pub enum EvmCdArrayError {
1040    InvalidBounds,
1041    TooShort,
1042    TooLong,
1043}
1044
1045pub struct EvmCdArray<T, const MIN: usize, const CAP: usize> {
1046    len: usize,
1047    values: [core::mem::MaybeUninit<T>; CAP],
1048}
1049
1050impl<T, const MIN: usize, const CAP: usize> EvmCdArray<T, MIN, CAP> {
1051    fn empty() -> Self {
1052        Self {
1053            len: 0,
1054            values: [const { core::mem::MaybeUninit::uninit() }; CAP],
1055        }
1056    }
1057
1058    fn validate_len(len: usize) -> Result<(), EvmCdArrayError> {
1059        if MIN > CAP {
1060            return Err(EvmCdArrayError::InvalidBounds);
1061        }
1062        if len < MIN {
1063            return Err(EvmCdArrayError::TooShort);
1064        }
1065        if len > CAP {
1066            return Err(EvmCdArrayError::TooLong);
1067        }
1068        Ok(())
1069    }
1070
1071    fn push(&mut self, value: T) {
1072        debug_assert!(self.len < CAP);
1073        self.values[self.len].write(value);
1074        self.len += 1;
1075    }
1076
1077    pub fn try_from_array(values: [T; CAP], len: usize) -> Result<Self, EvmCdArrayError> {
1078        Self::validate_len(len)?;
1079        let mut out = Self::empty();
1080        for value in values.into_iter().take(len) {
1081            out.push(value);
1082        }
1083        Ok(out)
1084    }
1085
1086    pub fn try_from_slice(values: &[T]) -> Result<Self, EvmCdArrayError>
1087    where
1088        T: Clone,
1089    {
1090        Self::validate_len(values.len())?;
1091        let mut out = Self::empty();
1092        for value in values {
1093            out.push(value.clone());
1094        }
1095        Ok(out)
1096    }
1097
1098    pub const fn len(&self) -> usize {
1099        self.len
1100    }
1101
1102    pub const fn is_empty(&self) -> bool {
1103        self.len == 0
1104    }
1105
1106    pub const fn capacity(&self) -> usize {
1107        CAP
1108    }
1109
1110    pub fn as_slice(&self) -> &[T] {
1111        // SAFETY: the first `len` slots are initialized by every constructor
1112        // and `push`, and `len` can never exceed CAP.
1113        unsafe { core::slice::from_raw_parts(self.values.as_ptr().cast::<T>(), self.len) }
1114    }
1115}
1116
1117impl<T, const MIN: usize, const CAP: usize> Drop for EvmCdArray<T, MIN, CAP> {
1118    fn drop(&mut self) {
1119        for value in &mut self.values[..self.len] {
1120            // SAFETY: exactly the first `len` slots are initialized.
1121            unsafe { value.assume_init_drop() };
1122        }
1123    }
1124}
1125
1126impl<T: Clone, const MIN: usize, const CAP: usize> Clone for EvmCdArray<T, MIN, CAP> {
1127    fn clone(&self) -> Self {
1128        Self::try_from_slice(self.as_slice()).expect("an existing EvmCdArray has valid bounds")
1129    }
1130}
1131
1132impl<T: core::fmt::Debug, const MIN: usize, const CAP: usize> core::fmt::Debug
1133    for EvmCdArray<T, MIN, CAP>
1134{
1135    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1136        formatter.debug_list().entries(self.as_slice()).finish()
1137    }
1138}
1139
1140impl<T: PartialEq, const MIN: usize, const CAP: usize> PartialEq for EvmCdArray<T, MIN, CAP> {
1141    fn eq(&self, other: &Self) -> bool {
1142        self.as_slice() == other.as_slice()
1143    }
1144}
1145
1146impl<T: Eq, const MIN: usize, const CAP: usize> Eq for EvmCdArray<T, MIN, CAP> {}
1147
1148impl<T, const MIN: usize, const CAP: usize> AsRef<[T]> for EvmCdArray<T, MIN, CAP> {
1149    fn as_ref(&self) -> &[T] {
1150        self.as_slice()
1151    }
1152}
1153
1154impl<T> EvmCdSerialise for &[T]
1155where
1156    T: EvmCdSerialise,
1157{
1158    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1159        U::from_u32(32).serialise_value(writer)?;
1160        self.serialise_abi_tail(writer)
1161    }
1162
1163    fn is_abi_dynamic() -> bool {
1164        true
1165    }
1166
1167    fn abi_tail_size(&self) -> usize {
1168        self.len()
1169            .saturating_mul(T::abi_head_size())
1170            .saturating_add(32)
1171            .saturating_add(self.iter().fold(0usize, |size, value| {
1172                size.saturating_add(value.abi_tail_size())
1173            }))
1174    }
1175
1176    fn serialise_abi_head<W: Write>(
1177        &self,
1178        tail_offset: usize,
1179        writer: &mut W,
1180    ) -> Result<(), Error> {
1181        U::from_usize(tail_offset).serialise_value(writer)
1182    }
1183
1184    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1185        U::from_usize(self.len()).serialise_value(writer)?;
1186        let mut tail_offset = self
1187            .len()
1188            .checked_mul(T::abi_head_size())
1189            .ok_or_else(invalid_data)?;
1190        for value in *self {
1191            value.serialise_abi_head(tail_offset, writer)?;
1192            tail_offset = tail_offset
1193                .checked_add(value.abi_tail_size())
1194                .ok_or_else(invalid_data)?;
1195        }
1196        for value in *self {
1197            value.serialise_abi_tail(writer)?;
1198        }
1199        Ok(())
1200    }
1201
1202    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1203        T::append_abi_type(hasher).update(b"[]")
1204    }
1205}
1206
1207impl<T, const MIN: usize, const CAP: usize> EvmCdSerialise for EvmCdArray<T, MIN, CAP>
1208where
1209    T: EvmCdSerialise,
1210{
1211    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1212        U::from_u32(32).serialise_value(writer)?;
1213        self.serialise_abi_tail(writer)
1214    }
1215
1216    fn is_abi_dynamic() -> bool {
1217        true
1218    }
1219
1220    fn abi_tail_size(&self) -> usize {
1221        self.len
1222            .saturating_mul(T::abi_head_size())
1223            .saturating_add(32)
1224            .saturating_add(self.as_slice().iter().fold(0usize, |size, value| {
1225                size.saturating_add(value.abi_tail_size())
1226            }))
1227    }
1228
1229    fn serialise_abi_head<W: Write>(
1230        &self,
1231        tail_offset: usize,
1232        writer: &mut W,
1233    ) -> Result<(), Error> {
1234        U::from_usize(tail_offset).serialise_value(writer)
1235    }
1236
1237    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1238        U::from_usize(self.len).serialise_value(writer)?;
1239        let mut tail_offset = self
1240            .len
1241            .checked_mul(T::abi_head_size())
1242            .ok_or_else(invalid_data)?;
1243        for value in self.as_slice() {
1244            value.serialise_abi_head(tail_offset, writer)?;
1245            tail_offset = tail_offset
1246                .checked_add(value.abi_tail_size())
1247                .ok_or_else(invalid_data)?;
1248        }
1249        for value in self.as_slice() {
1250            value.serialise_abi_tail(writer)?;
1251        }
1252        Ok(())
1253    }
1254
1255    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1256        T::append_abi_type(hasher).update(b"[]")
1257    }
1258}
1259
1260impl<T, const MIN: usize, const CAP: usize> EvmCdDeserialise for EvmCdArray<T, MIN, CAP>
1261where
1262    T: EvmCdDeserialise,
1263{
1264    type Buffer = <<T::Buffer as EvmCdDecodeBuffer>::Kind as EvmCdBufferKind>::Buffer<(
1265        [u8; 64],
1266        [T::Buffer; CAP],
1267    )>;
1268
1269    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1270        if read_usize_word(reader)? != 32 {
1271            return Err(invalid_data());
1272        }
1273        Self::deserialise_tail(reader)
1274    }
1275
1276    fn is_abi_dynamic() -> bool {
1277        true
1278    }
1279
1280    fn abi_tail_size(&self) -> usize {
1281        self.len
1282            .saturating_mul(T::abi_head_size())
1283            .saturating_add(32)
1284            .saturating_add(self.as_slice().iter().fold(0usize, |size, value| {
1285                size.saturating_add(value.abi_tail_size())
1286            }))
1287    }
1288
1289    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1290        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1291    }
1292
1293    fn deserialise_abi_finish<R: Read>(
1294        head: EvmCdHead<Self>,
1295        expected_tail_offset: usize,
1296        reader: &mut R,
1297    ) -> Result<Self, Error> {
1298        match head {
1299            EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1300                Self::deserialise_tail(reader)
1301            }
1302            _ => Err(invalid_data()),
1303        }
1304    }
1305
1306    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1307        T::append_abi_type(hasher).update(b"[]")
1308    }
1309}
1310
1311impl<T, const MIN: usize, const CAP: usize> EvmCdArray<T, MIN, CAP>
1312where
1313    T: EvmCdDeserialise,
1314{
1315    fn deserialise_tail<R: Read>(reader: &mut R) -> Result<Self, Error> {
1316        let len = read_usize_word(reader)?;
1317        Self::validate_len(len).map_err(|_| invalid_data())?;
1318        let mut out = Self::empty();
1319
1320        if T::is_abi_dynamic() {
1321            let mut offsets = [0usize; CAP];
1322            for offset in &mut offsets[..len] {
1323                match T::deserialise_abi_head(reader)? {
1324                    EvmCdHead::Offset(value) => *offset = value,
1325                    EvmCdHead::Value(_) => return Err(invalid_data()),
1326                }
1327            }
1328            let mut expected_tail_offset = len
1329                .checked_mul(T::abi_head_size())
1330                .ok_or_else(invalid_data)?;
1331            for offset in offsets[..len].iter().copied() {
1332                let value = T::deserialise_abi_finish(
1333                    EvmCdHead::Offset(offset),
1334                    expected_tail_offset,
1335                    reader,
1336                )?;
1337                expected_tail_offset = expected_tail_offset
1338                    .checked_add(value.abi_tail_size())
1339                    .ok_or_else(invalid_data)?;
1340                out.push(value);
1341            }
1342        } else {
1343            for _ in 0..len {
1344                let head = T::deserialise_abi_head(reader)?;
1345                out.push(T::deserialise_abi_finish(head, 0, reader)?);
1346            }
1347        }
1348        Ok(out)
1349    }
1350}
1351
1352#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1353pub enum EvmCdBytesError {
1354    TooLong,
1355}
1356
1357#[derive(Clone)]
1358pub struct EvmCdBytes<const CAP: usize> {
1359    pub len: usize,
1360    pub bytes: [u8; CAP],
1361}
1362
1363impl<const CAP: usize> EvmCdBytes<CAP> {
1364    pub const fn new() -> Self {
1365        Self {
1366            len: 0,
1367            bytes: [0; CAP],
1368        }
1369    }
1370
1371    pub fn try_from_slice(value: &[u8]) -> Result<Self, EvmCdBytesError> {
1372        if value.len() > CAP {
1373            return Err(EvmCdBytesError::TooLong);
1374        }
1375        let mut bytes = [0; CAP];
1376        bytes[..value.len()].copy_from_slice(value);
1377        Ok(Self {
1378            len: value.len(),
1379            bytes,
1380        })
1381    }
1382
1383    pub fn try_from_serialised<T: EvmCdSerialise + ?Sized>(value: &T) -> Result<Self, Error> {
1384        let mut bytes = Self::new();
1385        value.serialise(&mut bytes)?;
1386        Ok(bytes)
1387    }
1388
1389    pub const fn len(&self) -> usize {
1390        self.len
1391    }
1392
1393    pub const fn is_empty(&self) -> bool {
1394        self.len == 0
1395    }
1396
1397    pub const fn capacity(&self) -> usize {
1398        CAP
1399    }
1400
1401    pub fn as_slice(&self) -> &[u8] {
1402        &self.bytes[..self.len]
1403    }
1404
1405    pub fn clear(&mut self) {
1406        self.len = 0;
1407    }
1408
1409    pub fn extend_from_slice(&mut self, value: &[u8]) -> Result<(), EvmCdBytesError> {
1410        let end = self
1411            .len
1412            .checked_add(value.len())
1413            .filter(|end| *end <= CAP)
1414            .ok_or(EvmCdBytesError::TooLong)?;
1415        self.bytes[self.len..end].copy_from_slice(value);
1416        self.len = end;
1417        Ok(())
1418    }
1419}
1420
1421impl<const CAP: usize> Default for EvmCdBytes<CAP> {
1422    fn default() -> Self {
1423        Self::new()
1424    }
1425}
1426
1427impl<const CAP: usize> From<[u8; CAP]> for EvmCdBytes<CAP> {
1428    fn from(bytes: [u8; CAP]) -> Self {
1429        Self { len: CAP, bytes }
1430    }
1431}
1432
1433impl<const CAP: usize> TryFrom<&[u8]> for EvmCdBytes<CAP> {
1434    type Error = EvmCdBytesError;
1435
1436    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
1437        Self::try_from_slice(value)
1438    }
1439}
1440
1441#[cfg(feature = "alloc")]
1442impl<const CAP: usize> TryFrom<Vec<u8>> for EvmCdBytes<CAP> {
1443    type Error = EvmCdBytesError;
1444
1445    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
1446        Self::try_from_slice(&value)
1447    }
1448}
1449
1450impl<const CAP: usize> AsRef<[u8]> for EvmCdBytes<CAP> {
1451    fn as_ref(&self) -> &[u8] {
1452        self.as_slice()
1453    }
1454}
1455
1456impl<const CAP: usize> core::fmt::Debug for EvmCdBytes<CAP> {
1457    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1458        core::fmt::Debug::fmt(self.as_slice(), formatter)
1459    }
1460}
1461
1462impl<const CAP: usize> PartialEq for EvmCdBytes<CAP> {
1463    fn eq(&self, other: &Self) -> bool {
1464        self.as_slice() == other.as_slice()
1465    }
1466}
1467
1468impl<const CAP: usize> Eq for EvmCdBytes<CAP> {}
1469
1470impl<const CAP: usize> PartialOrd for EvmCdBytes<CAP> {
1471    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1472        Some(self.cmp(other))
1473    }
1474}
1475
1476impl<const CAP: usize> Ord for EvmCdBytes<CAP> {
1477    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1478        self.as_slice().cmp(other.as_slice())
1479    }
1480}
1481
1482impl<const CAP: usize> core::hash::Hash for EvmCdBytes<CAP> {
1483    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1484        core::hash::Hash::hash(self.as_slice(), state)
1485    }
1486}
1487
1488#[doc(hidden)]
1489pub struct EvmCdBytesWriter<'a, const CAP: usize> {
1490    pub bytes: &'a mut EvmCdBytes<CAP>,
1491}
1492
1493#[cfg(not(feature = "std"))]
1494impl<const CAP: usize> Write for EvmCdBytesWriter<'_, CAP> {
1495    fn write(&mut self, value: &[u8]) -> Result<usize, Error> {
1496        let written = core::cmp::min(CAP - self.bytes.len, value.len());
1497        let end = self.bytes.len + written;
1498        self.bytes.bytes[self.bytes.len..end].copy_from_slice(&value[..written]);
1499        self.bytes.len = end;
1500        Ok(written)
1501    }
1502
1503    fn flush(&mut self) -> Result<(), Error> {
1504        Ok(())
1505    }
1506
1507    fn is_empty(&self) -> bool {
1508        self.bytes.len == CAP
1509    }
1510}
1511
1512#[cfg(feature = "std")]
1513impl<const CAP: usize> Write for EvmCdBytesWriter<'_, CAP> {
1514    fn write(&mut self, value: &[u8]) -> Result<usize, Error> {
1515        let written = core::cmp::min(CAP - self.bytes.len, value.len());
1516        let end = self.bytes.len + written;
1517        self.bytes.bytes[self.bytes.len..end].copy_from_slice(&value[..written]);
1518        self.bytes.len = end;
1519        Ok(written)
1520    }
1521
1522    fn flush(&mut self) -> Result<(), Error> {
1523        Ok(())
1524    }
1525}
1526
1527impl<const CAP: usize> EvmCdWriteTarget for EvmCdBytes<CAP> {
1528    type Writer<'a> = EvmCdBytesWriter<'a, CAP>;
1529
1530    fn writer(&mut self) -> Self::Writer<'_> {
1531        EvmCdBytesWriter { bytes: self }
1532    }
1533}
1534
1535impl<const CAP: usize> EvmCdSerialise for EvmCdBytes<CAP> {
1536    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1537        write_dynamic_bytes(self.as_slice(), writer)
1538    }
1539
1540    fn is_abi_dynamic() -> bool {
1541        true
1542    }
1543
1544    fn abi_tail_size(&self) -> usize {
1545        dynamic_tail_size(self.len)
1546    }
1547
1548    fn serialise_abi_head<W: Write>(
1549        &self,
1550        tail_offset: usize,
1551        writer: &mut W,
1552    ) -> Result<(), Error> {
1553        U::from_usize(tail_offset).serialise_value(writer)
1554    }
1555
1556    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1557        write_dynamic_tail(self.as_slice(), writer)
1558    }
1559
1560    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1561        hasher.update(b"bytes")
1562    }
1563}
1564
1565impl<const CAP: usize> EvmCdDeserialise for EvmCdBytes<CAP> {
1566    type Buffer = EvmCdBuffer<([u8; 64], [u8; CAP], [u8; 31])>;
1567
1568    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1569        let (bytes, len) = read_dynamic_bytes::<CAP, _>(reader)?;
1570        Ok(Self { len, bytes })
1571    }
1572
1573    fn is_abi_dynamic() -> bool {
1574        true
1575    }
1576
1577    fn abi_tail_size(&self) -> usize {
1578        dynamic_tail_size(self.len)
1579    }
1580
1581    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1582        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1583    }
1584
1585    fn deserialise_abi_finish<R: Read>(
1586        head: EvmCdHead<Self>,
1587        expected_tail_offset: usize,
1588        reader: &mut R,
1589    ) -> Result<Self, Error> {
1590        match head {
1591            EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1592                let (bytes, len) = read_dynamic_tail::<CAP, _>(reader)?;
1593                Ok(Self { len, bytes })
1594            }
1595            _ => Err(invalid_data()),
1596        }
1597    }
1598
1599    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1600        hasher.update(b"bytes")
1601    }
1602}
1603
1604#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1605pub enum EvmCdStringError {
1606    InvalidBounds,
1607    TooShort,
1608    TooLong,
1609}
1610
1611#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1612pub struct EvmCdString<const MIN: usize, const CAP: usize> {
1613    pub len: usize,
1614    pub bytes: [u8; CAP],
1615}
1616
1617impl<const MIN: usize, const CAP: usize> EvmCdString<MIN, CAP> {
1618    pub fn try_from_str(value: &str) -> Result<Self, EvmCdStringError> {
1619        if MIN > CAP {
1620            return Err(EvmCdStringError::InvalidBounds);
1621        }
1622        if value.len() < MIN {
1623            return Err(EvmCdStringError::TooShort);
1624        }
1625        if value.len() > CAP {
1626            return Err(EvmCdStringError::TooLong);
1627        }
1628        let mut bytes = [0u8; CAP];
1629        bytes[..value.len()].copy_from_slice(value.as_bytes());
1630        Ok(Self {
1631            len: value.len(),
1632            bytes,
1633        })
1634    }
1635
1636    pub const fn len(&self) -> usize {
1637        self.len
1638    }
1639
1640    pub const fn is_empty(&self) -> bool {
1641        self.len == 0
1642    }
1643
1644    pub const fn capacity(&self) -> usize {
1645        CAP
1646    }
1647
1648    pub fn as_bytes(&self) -> &[u8] {
1649        &self.bytes[..self.len]
1650    }
1651
1652    pub fn as_str(&self) -> &str {
1653        // SAFETY: constructors and deserialisation validate UTF-8, and no API
1654        // exposes mutable access to the initialized bytes.
1655        unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
1656    }
1657}
1658
1659impl<const MIN: usize, const CAP: usize> TryFrom<&str> for EvmCdString<MIN, CAP> {
1660    type Error = EvmCdStringError;
1661
1662    fn try_from(value: &str) -> Result<Self, Self::Error> {
1663        Self::try_from_str(value)
1664    }
1665}
1666
1667impl<const MIN: usize, const CAP: usize> AsRef<str> for EvmCdString<MIN, CAP> {
1668    fn as_ref(&self) -> &str {
1669        self.as_str()
1670    }
1671}
1672
1673impl<const MIN: usize, const CAP: usize> AsRef<[u8]> for EvmCdString<MIN, CAP> {
1674    fn as_ref(&self) -> &[u8] {
1675        self.as_bytes()
1676    }
1677}
1678
1679impl<const MIN: usize, const CAP: usize> core::borrow::Borrow<str> for EvmCdString<MIN, CAP> {
1680    fn borrow(&self) -> &str {
1681        self.as_str()
1682    }
1683}
1684
1685impl<const MIN: usize, const CAP: usize> core::fmt::Display for EvmCdString<MIN, CAP> {
1686    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1687        formatter.write_str(self.as_str())
1688    }
1689}
1690
1691impl<const MIN: usize, const CAP: usize> core::fmt::Debug for EvmCdString<MIN, CAP> {
1692    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1693        core::fmt::Debug::fmt(self.as_str(), formatter)
1694    }
1695}
1696
1697impl<const MIN: usize, const CAP: usize> core::str::FromStr for EvmCdString<MIN, CAP> {
1698    type Err = EvmCdStringError;
1699
1700    fn from_str(value: &str) -> Result<Self, Self::Err> {
1701        Self::try_from_str(value)
1702    }
1703}
1704
1705impl<const MIN: usize, const CAP: usize> EvmCdSerialise for EvmCdString<MIN, CAP> {
1706    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1707        write_dynamic_bytes(self.as_bytes(), writer)
1708    }
1709
1710    fn is_abi_dynamic() -> bool {
1711        true
1712    }
1713
1714    fn abi_tail_size(&self) -> usize {
1715        dynamic_tail_size(self.len)
1716    }
1717
1718    fn serialise_abi_head<W: Write>(
1719        &self,
1720        tail_offset: usize,
1721        writer: &mut W,
1722    ) -> Result<(), Error> {
1723        U::from_usize(tail_offset).serialise_value(writer)
1724    }
1725
1726    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1727        write_dynamic_tail(self.as_bytes(), writer)
1728    }
1729
1730    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1731        hasher.update(b"string")
1732    }
1733}
1734
1735impl<const MIN: usize, const CAP: usize> EvmCdDeserialise for EvmCdString<MIN, CAP> {
1736    type Buffer = EvmCdBuffer<([u8; 64], [u8; CAP], [u8; 31])>;
1737
1738    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1739        if MIN > CAP {
1740            return Err(invalid_data());
1741        }
1742        let (bytes, len) = read_dynamic_bytes::<CAP, _>(reader)?;
1743        if len < MIN || core::str::from_utf8(&bytes[..len]).is_err() {
1744            return Err(invalid_data());
1745        }
1746        Ok(Self { len, bytes })
1747    }
1748
1749    fn is_abi_dynamic() -> bool {
1750        true
1751    }
1752
1753    fn abi_tail_size(&self) -> usize {
1754        dynamic_tail_size(self.len)
1755    }
1756
1757    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1758        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1759    }
1760
1761    fn deserialise_abi_finish<R: Read>(
1762        head: EvmCdHead<Self>,
1763        expected_tail_offset: usize,
1764        reader: &mut R,
1765    ) -> Result<Self, Error> {
1766        match head {
1767            EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1768                if MIN > CAP {
1769                    return Err(invalid_data());
1770                }
1771                let (bytes, len) = read_dynamic_tail::<CAP, _>(reader)?;
1772                if len < MIN || core::str::from_utf8(&bytes[..len]).is_err() {
1773                    return Err(invalid_data());
1774                }
1775                Ok(Self { len, bytes })
1776            }
1777            _ => Err(invalid_data()),
1778        }
1779    }
1780
1781    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1782        hasher.update(b"string")
1783    }
1784}
1785
1786#[cfg(feature = "alloc")]
1787impl<const MIN: usize, const CAP: usize> From<EvmCdString<MIN, CAP>> for String {
1788    fn from(value: EvmCdString<MIN, CAP>) -> Self {
1789        String::from(value.as_str())
1790    }
1791}
1792
1793#[cfg(feature = "alloc")]
1794fn vec_is_bytes<T: 'static>() -> bool {
1795    core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>()
1796}
1797
1798#[cfg(feature = "alloc")]
1799fn vec_as_bytes<T: 'static>(values: &[T]) -> &[u8] {
1800    debug_assert!(vec_is_bytes::<T>());
1801    // SAFETY: this helper is called only when TypeId proves that T is u8.
1802    unsafe { core::slice::from_raw_parts(values.as_ptr().cast::<u8>(), values.len()) }
1803}
1804
1805#[cfg(feature = "alloc")]
1806impl<T> EvmCdSerialise for Vec<T>
1807where
1808    T: EvmCdSerialise + 'static,
1809{
1810    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1811        U::from_u32(32).serialise_value(writer)?;
1812        self.serialise_abi_tail(writer)
1813    }
1814
1815    fn is_abi_dynamic() -> bool {
1816        true
1817    }
1818
1819    fn abi_tail_size(&self) -> usize {
1820        if vec_is_bytes::<T>() {
1821            dynamic_tail_size(self.len())
1822        } else {
1823            self.len()
1824                .saturating_mul(T::abi_head_size())
1825                .saturating_add(32)
1826                .saturating_add(self.iter().fold(0usize, |size, value| {
1827                    size.saturating_add(value.abi_tail_size())
1828                }))
1829        }
1830    }
1831
1832    fn serialise_abi_head<W: Write>(
1833        &self,
1834        tail_offset: usize,
1835        writer: &mut W,
1836    ) -> Result<(), Error> {
1837        U::from_usize(tail_offset).serialise_value(writer)
1838    }
1839
1840    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1841        if vec_is_bytes::<T>() {
1842            return write_dynamic_tail(vec_as_bytes(self), writer);
1843        }
1844
1845        U::from_usize(self.len()).serialise_value(writer)?;
1846        let mut tail_offset = self
1847            .len()
1848            .checked_mul(T::abi_head_size())
1849            .ok_or_else(invalid_data)?;
1850        for value in self {
1851            value.serialise_abi_head(tail_offset, writer)?;
1852            tail_offset = tail_offset
1853                .checked_add(value.abi_tail_size())
1854                .ok_or_else(invalid_data)?;
1855        }
1856        for value in self {
1857            value.serialise_abi_tail(writer)?;
1858        }
1859        Ok(())
1860    }
1861
1862    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1863        if vec_is_bytes::<T>() {
1864            hasher.update(b"bytes")
1865        } else {
1866            T::append_abi_type(hasher).update(b"[]")
1867        }
1868    }
1869}
1870
1871#[cfg(feature = "alloc")]
1872const MAX_ALLOC_DESERIALISE_LEN: usize = 16 * 1024 * 1024;
1873
1874#[cfg(feature = "alloc")]
1875fn read_vec_bytes_tail<R: Read>(reader: &mut R) -> Result<Vec<u8>, Error> {
1876    let len = read_usize_word(reader)?;
1877    if len > MAX_ALLOC_DESERIALISE_LEN {
1878        return Err(invalid_data());
1879    }
1880    let mut out = Vec::new();
1881    out.try_reserve_exact(len).map_err(|_| invalid_data())?;
1882    out.resize(len, 0);
1883    reader.read_exact(&mut out)?;
1884    let padding = (32 - len % 32) % 32;
1885    let mut padding_bytes = [0u8; 31];
1886    reader.read_exact(&mut padding_bytes[..padding])?;
1887    if padding_bytes[..padding].iter().any(|byte| *byte != 0) {
1888        return Err(invalid_data());
1889    }
1890    Ok(out)
1891}
1892
1893#[cfg(feature = "alloc")]
1894fn bytes_into_vec<T: 'static>(bytes: Vec<u8>) -> Vec<T> {
1895    debug_assert!(vec_is_bytes::<T>());
1896    let mut bytes = core::mem::ManuallyDrop::new(bytes);
1897    // SAFETY: TypeId proves that T is u8, so the allocation layout and elements match.
1898    unsafe {
1899        Vec::from_raw_parts(
1900            bytes.as_mut_ptr().cast::<T>(),
1901            bytes.len(),
1902            bytes.capacity(),
1903        )
1904    }
1905}
1906
1907#[cfg(feature = "alloc")]
1908fn validate_vec_array_len<T: EvmCdDeserialise>(len: usize) -> Result<(), Error> {
1909    let head_bytes = len
1910        .checked_mul(T::abi_head_size())
1911        .ok_or_else(invalid_data)?;
1912    let value_bytes = len
1913        .checked_mul(core::mem::size_of::<T>())
1914        .ok_or_else(invalid_data)?;
1915    let offset_bytes = if T::is_abi_dynamic() {
1916        len.checked_mul(core::mem::size_of::<usize>())
1917            .ok_or_else(invalid_data)?
1918    } else {
1919        0
1920    };
1921    if head_bytes > MAX_ALLOC_DESERIALISE_LEN
1922        || value_bytes > MAX_ALLOC_DESERIALISE_LEN
1923        || offset_bytes > MAX_ALLOC_DESERIALISE_LEN
1924    {
1925        return Err(invalid_data());
1926    }
1927    Ok(())
1928}
1929
1930#[cfg(feature = "alloc")]
1931fn read_vec_array_tail<T, R>(reader: &mut R) -> Result<Vec<T>, Error>
1932where
1933    T: EvmCdDeserialise + 'static,
1934    R: Read,
1935{
1936    let len = read_usize_word(reader)?;
1937    validate_vec_array_len::<T>(len)?;
1938
1939    let mut out = Vec::new();
1940    out.try_reserve_exact(len).map_err(|_| invalid_data())?;
1941    if T::is_abi_dynamic() {
1942        let mut offsets = Vec::new();
1943        offsets.try_reserve_exact(len).map_err(|_| invalid_data())?;
1944        for _ in 0..len {
1945            match T::deserialise_abi_head(reader)? {
1946                EvmCdHead::Offset(offset) => offsets.push(offset),
1947                EvmCdHead::Value(_) => return Err(invalid_data()),
1948            }
1949        }
1950        let mut expected_tail_offset = len
1951            .checked_mul(T::abi_head_size())
1952            .ok_or_else(invalid_data)?;
1953        for offset in offsets {
1954            let value =
1955                T::deserialise_abi_finish(EvmCdHead::Offset(offset), expected_tail_offset, reader)?;
1956            expected_tail_offset = expected_tail_offset
1957                .checked_add(value.abi_tail_size())
1958                .ok_or_else(invalid_data)?;
1959            out.push(value);
1960        }
1961    } else {
1962        for _ in 0..len {
1963            let head = T::deserialise_abi_head(reader)?;
1964            out.push(T::deserialise_abi_finish(head, 0, reader)?);
1965        }
1966    }
1967    Ok(out)
1968}
1969
1970#[cfg(feature = "alloc")]
1971fn read_vec_tail<T, R>(reader: &mut R) -> Result<Vec<T>, Error>
1972where
1973    T: EvmCdDeserialise + 'static,
1974    R: Read,
1975{
1976    if vec_is_bytes::<T>() {
1977        read_vec_bytes_tail(reader).map(bytes_into_vec)
1978    } else {
1979        read_vec_array_tail(reader)
1980    }
1981}
1982
1983#[cfg(feature = "alloc")]
1984impl<T> EvmCdDeserialise for Vec<T>
1985where
1986    T: EvmCdDeserialise + 'static,
1987{
1988    type Buffer = EvmCdDynamicBuffer<()>;
1989
1990    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1991        if read_usize_word(reader)? != 32 {
1992            return Err(invalid_data());
1993        }
1994        read_vec_tail(reader)
1995    }
1996
1997    fn is_abi_dynamic() -> bool {
1998        true
1999    }
2000
2001    fn abi_tail_size(&self) -> usize {
2002        if vec_is_bytes::<T>() {
2003            dynamic_tail_size(self.len())
2004        } else {
2005            self.len()
2006                .saturating_mul(T::abi_head_size())
2007                .saturating_add(32)
2008                .saturating_add(self.iter().fold(0usize, |size, value| {
2009                    size.saturating_add(value.abi_tail_size())
2010                }))
2011        }
2012    }
2013
2014    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
2015        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
2016    }
2017
2018    fn deserialise_abi_finish<R: Read>(
2019        head: EvmCdHead<Self>,
2020        expected_tail_offset: usize,
2021        reader: &mut R,
2022    ) -> Result<Self, Error> {
2023        match head {
2024            EvmCdHead::Offset(offset) if offset == expected_tail_offset => read_vec_tail(reader),
2025            _ => Err(invalid_data()),
2026        }
2027    }
2028
2029    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
2030        if vec_is_bytes::<T>() {
2031            hasher.update(b"bytes")
2032        } else {
2033            T::append_abi_type(hasher).update(b"[]")
2034        }
2035    }
2036}
2037
2038#[cfg(all(test, not(feature = "std")))]
2039mod tests {
2040    use super::{EvmCdDeserialise, EvmCdSerialise};
2041
2042    #[derive(
2043        Debug, PartialEq, Eq, bobcat_cd_derive::EvmCdSerialise, bobcat_cd_derive::EvmCdDeserialise,
2044    )]
2045    struct SliceValue {
2046        small: u8,
2047        large: u32,
2048    }
2049
2050    #[test]
2051    fn mutable_slice_is_a_serialisation_writer_and_deserialisation_reader() {
2052        let value = SliceValue {
2053            small: 7,
2054            large: 0x1234_5678,
2055        };
2056        let mut storage = [0u8; 64];
2057
2058        let mut writer = storage.as_mut_slice();
2059        value.serialise(&mut writer).unwrap();
2060        assert!(writer.is_empty());
2061
2062        let mut reader = storage.as_mut_slice();
2063        assert_eq!(SliceValue::deserialise_reader(&mut reader).unwrap(), value);
2064        assert!(reader.is_empty());
2065    }
2066}