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 From<EvmCdAddress> for U {
964    fn from(address: EvmCdAddress) -> Self {
965        let mut word = [0u8; 32];
966        word[12..].copy_from_slice(address.as_array());
967        Self::from(word)
968    }
969}
970
971impl AsRef<[u8; 20]> for EvmCdAddress {
972    fn as_ref(&self) -> &[u8; 20] {
973        self.as_array()
974    }
975}
976
977impl AsRef<[u8]> for EvmCdAddress {
978    fn as_ref(&self) -> &[u8] {
979        self.as_array()
980    }
981}
982
983impl EvmCdSerialise for EvmCdAddress {
984    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
985        writer.write_all(&[0; 12])?;
986        writer.write_all(&self.0)
987    }
988
989    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
990        hasher.update(b"address")
991    }
992}
993
994impl EvmCdDeserialise for EvmCdAddress {
995    fixed_deserialise_buffer!([u8; 32]);
996
997    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
998        let mut word = [0u8; 32];
999        reader.read_exact(&mut word)?;
1000        if word[..12].iter().any(|byte| *byte != 0) {
1001            return Err(invalid_data());
1002        }
1003        Ok(Self(word[12..].try_into().unwrap()))
1004    }
1005
1006    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1007        hasher.update(b"address")
1008    }
1009}
1010
1011impl<const N: usize> EvmCdSerialise for [u8; N] {
1012    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1013        if N == 0 || N > 32 {
1014            return Err(invalid_data());
1015        }
1016        writer.write_all(self)?;
1017        const ZEROES: [u8; 32] = [0; 32];
1018        writer.write_all(&ZEROES[..32 - N])
1019    }
1020
1021    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1022        hasher.update(b"bytes").update_usize(N)
1023    }
1024}
1025
1026impl<const N: usize> EvmCdDeserialise for [u8; N] {
1027    fixed_deserialise_buffer!([u8; 32]);
1028
1029    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1030        if N == 0 || N > 32 {
1031            return Err(invalid_data());
1032        }
1033        let mut word = [0u8; 32];
1034        reader.read_exact(&mut word)?;
1035        if word[N..].iter().any(|byte| *byte != 0) {
1036            return Err(invalid_data());
1037        }
1038        Ok(word[..N].try_into().unwrap())
1039    }
1040
1041    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1042        hasher.update(b"bytes").update_usize(N)
1043    }
1044}
1045
1046#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1047pub enum EvmCdArrayError {
1048    InvalidBounds,
1049    TooShort,
1050    TooLong,
1051}
1052
1053pub struct EvmCdArray<T, const MIN: usize, const CAP: usize> {
1054    len: usize,
1055    values: [core::mem::MaybeUninit<T>; CAP],
1056}
1057
1058impl<T, const MIN: usize, const CAP: usize> EvmCdArray<T, MIN, CAP> {
1059    fn empty() -> Self {
1060        Self {
1061            len: 0,
1062            values: [const { core::mem::MaybeUninit::uninit() }; CAP],
1063        }
1064    }
1065
1066    fn validate_len(len: usize) -> Result<(), EvmCdArrayError> {
1067        if MIN > CAP {
1068            return Err(EvmCdArrayError::InvalidBounds);
1069        }
1070        if len < MIN {
1071            return Err(EvmCdArrayError::TooShort);
1072        }
1073        if len > CAP {
1074            return Err(EvmCdArrayError::TooLong);
1075        }
1076        Ok(())
1077    }
1078
1079    fn push(&mut self, value: T) {
1080        debug_assert!(self.len < CAP);
1081        self.values[self.len].write(value);
1082        self.len += 1;
1083    }
1084
1085    pub fn try_from_array(values: [T; CAP], len: usize) -> Result<Self, EvmCdArrayError> {
1086        Self::validate_len(len)?;
1087        let mut out = Self::empty();
1088        for value in values.into_iter().take(len) {
1089            out.push(value);
1090        }
1091        Ok(out)
1092    }
1093
1094    pub fn try_from_slice(values: &[T]) -> Result<Self, EvmCdArrayError>
1095    where
1096        T: Clone,
1097    {
1098        Self::validate_len(values.len())?;
1099        let mut out = Self::empty();
1100        for value in values {
1101            out.push(value.clone());
1102        }
1103        Ok(out)
1104    }
1105
1106    pub const fn len(&self) -> usize {
1107        self.len
1108    }
1109
1110    pub const fn is_empty(&self) -> bool {
1111        self.len == 0
1112    }
1113
1114    pub const fn capacity(&self) -> usize {
1115        CAP
1116    }
1117
1118    pub fn as_slice(&self) -> &[T] {
1119        // SAFETY: the first `len` slots are initialized by every constructor
1120        // and `push`, and `len` can never exceed CAP.
1121        unsafe { core::slice::from_raw_parts(self.values.as_ptr().cast::<T>(), self.len) }
1122    }
1123}
1124
1125impl<T, const MIN: usize, const CAP: usize> Drop for EvmCdArray<T, MIN, CAP> {
1126    fn drop(&mut self) {
1127        for value in &mut self.values[..self.len] {
1128            // SAFETY: exactly the first `len` slots are initialized.
1129            unsafe { value.assume_init_drop() };
1130        }
1131    }
1132}
1133
1134impl<T: Clone, const MIN: usize, const CAP: usize> Clone for EvmCdArray<T, MIN, CAP> {
1135    fn clone(&self) -> Self {
1136        Self::try_from_slice(self.as_slice()).expect("an existing EvmCdArray has valid bounds")
1137    }
1138}
1139
1140impl<T: core::fmt::Debug, const MIN: usize, const CAP: usize> core::fmt::Debug
1141    for EvmCdArray<T, MIN, CAP>
1142{
1143    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1144        formatter.debug_list().entries(self.as_slice()).finish()
1145    }
1146}
1147
1148impl<T: PartialEq, const MIN: usize, const CAP: usize> PartialEq for EvmCdArray<T, MIN, CAP> {
1149    fn eq(&self, other: &Self) -> bool {
1150        self.as_slice() == other.as_slice()
1151    }
1152}
1153
1154impl<T: Eq, const MIN: usize, const CAP: usize> Eq for EvmCdArray<T, MIN, CAP> {}
1155
1156impl<T, const MIN: usize, const CAP: usize> AsRef<[T]> for EvmCdArray<T, MIN, CAP> {
1157    fn as_ref(&self) -> &[T] {
1158        self.as_slice()
1159    }
1160}
1161
1162impl<T> EvmCdSerialise for &[T]
1163where
1164    T: EvmCdSerialise,
1165{
1166    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1167        U::from_u32(32).serialise_value(writer)?;
1168        self.serialise_abi_tail(writer)
1169    }
1170
1171    fn is_abi_dynamic() -> bool {
1172        true
1173    }
1174
1175    fn abi_tail_size(&self) -> usize {
1176        self.len()
1177            .saturating_mul(T::abi_head_size())
1178            .saturating_add(32)
1179            .saturating_add(self.iter().fold(0usize, |size, value| {
1180                size.saturating_add(value.abi_tail_size())
1181            }))
1182    }
1183
1184    fn serialise_abi_head<W: Write>(
1185        &self,
1186        tail_offset: usize,
1187        writer: &mut W,
1188    ) -> Result<(), Error> {
1189        U::from_usize(tail_offset).serialise_value(writer)
1190    }
1191
1192    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1193        U::from_usize(self.len()).serialise_value(writer)?;
1194        let mut tail_offset = self
1195            .len()
1196            .checked_mul(T::abi_head_size())
1197            .ok_or_else(invalid_data)?;
1198        for value in *self {
1199            value.serialise_abi_head(tail_offset, writer)?;
1200            tail_offset = tail_offset
1201                .checked_add(value.abi_tail_size())
1202                .ok_or_else(invalid_data)?;
1203        }
1204        for value in *self {
1205            value.serialise_abi_tail(writer)?;
1206        }
1207        Ok(())
1208    }
1209
1210    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1211        T::append_abi_type(hasher).update(b"[]")
1212    }
1213}
1214
1215impl<T, const MIN: usize, const CAP: usize> EvmCdSerialise for EvmCdArray<T, MIN, CAP>
1216where
1217    T: EvmCdSerialise,
1218{
1219    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1220        U::from_u32(32).serialise_value(writer)?;
1221        self.serialise_abi_tail(writer)
1222    }
1223
1224    fn is_abi_dynamic() -> bool {
1225        true
1226    }
1227
1228    fn abi_tail_size(&self) -> usize {
1229        self.len
1230            .saturating_mul(T::abi_head_size())
1231            .saturating_add(32)
1232            .saturating_add(self.as_slice().iter().fold(0usize, |size, value| {
1233                size.saturating_add(value.abi_tail_size())
1234            }))
1235    }
1236
1237    fn serialise_abi_head<W: Write>(
1238        &self,
1239        tail_offset: usize,
1240        writer: &mut W,
1241    ) -> Result<(), Error> {
1242        U::from_usize(tail_offset).serialise_value(writer)
1243    }
1244
1245    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1246        U::from_usize(self.len).serialise_value(writer)?;
1247        let mut tail_offset = self
1248            .len
1249            .checked_mul(T::abi_head_size())
1250            .ok_or_else(invalid_data)?;
1251        for value in self.as_slice() {
1252            value.serialise_abi_head(tail_offset, writer)?;
1253            tail_offset = tail_offset
1254                .checked_add(value.abi_tail_size())
1255                .ok_or_else(invalid_data)?;
1256        }
1257        for value in self.as_slice() {
1258            value.serialise_abi_tail(writer)?;
1259        }
1260        Ok(())
1261    }
1262
1263    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1264        T::append_abi_type(hasher).update(b"[]")
1265    }
1266}
1267
1268impl<T, const MIN: usize, const CAP: usize> EvmCdDeserialise for EvmCdArray<T, MIN, CAP>
1269where
1270    T: EvmCdDeserialise,
1271{
1272    type Buffer = <<T::Buffer as EvmCdDecodeBuffer>::Kind as EvmCdBufferKind>::Buffer<(
1273        [u8; 64],
1274        [T::Buffer; CAP],
1275    )>;
1276
1277    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1278        if read_usize_word(reader)? != 32 {
1279            return Err(invalid_data());
1280        }
1281        Self::deserialise_tail(reader)
1282    }
1283
1284    fn is_abi_dynamic() -> bool {
1285        true
1286    }
1287
1288    fn abi_tail_size(&self) -> usize {
1289        self.len
1290            .saturating_mul(T::abi_head_size())
1291            .saturating_add(32)
1292            .saturating_add(self.as_slice().iter().fold(0usize, |size, value| {
1293                size.saturating_add(value.abi_tail_size())
1294            }))
1295    }
1296
1297    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1298        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1299    }
1300
1301    fn deserialise_abi_finish<R: Read>(
1302        head: EvmCdHead<Self>,
1303        expected_tail_offset: usize,
1304        reader: &mut R,
1305    ) -> Result<Self, Error> {
1306        match head {
1307            EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1308                Self::deserialise_tail(reader)
1309            }
1310            _ => Err(invalid_data()),
1311        }
1312    }
1313
1314    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1315        T::append_abi_type(hasher).update(b"[]")
1316    }
1317}
1318
1319impl<T, const MIN: usize, const CAP: usize> EvmCdArray<T, MIN, CAP>
1320where
1321    T: EvmCdDeserialise,
1322{
1323    fn deserialise_tail<R: Read>(reader: &mut R) -> Result<Self, Error> {
1324        let len = read_usize_word(reader)?;
1325        Self::validate_len(len).map_err(|_| invalid_data())?;
1326        let mut out = Self::empty();
1327
1328        if T::is_abi_dynamic() {
1329            let mut offsets = [0usize; CAP];
1330            for offset in &mut offsets[..len] {
1331                match T::deserialise_abi_head(reader)? {
1332                    EvmCdHead::Offset(value) => *offset = value,
1333                    EvmCdHead::Value(_) => return Err(invalid_data()),
1334                }
1335            }
1336            let mut expected_tail_offset = len
1337                .checked_mul(T::abi_head_size())
1338                .ok_or_else(invalid_data)?;
1339            for offset in offsets[..len].iter().copied() {
1340                let value = T::deserialise_abi_finish(
1341                    EvmCdHead::Offset(offset),
1342                    expected_tail_offset,
1343                    reader,
1344                )?;
1345                expected_tail_offset = expected_tail_offset
1346                    .checked_add(value.abi_tail_size())
1347                    .ok_or_else(invalid_data)?;
1348                out.push(value);
1349            }
1350        } else {
1351            for _ in 0..len {
1352                let head = T::deserialise_abi_head(reader)?;
1353                out.push(T::deserialise_abi_finish(head, 0, reader)?);
1354            }
1355        }
1356        Ok(out)
1357    }
1358}
1359
1360#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1361pub enum EvmCdBytesError {
1362    TooLong,
1363}
1364
1365#[derive(Clone)]
1366pub struct EvmCdBytes<const CAP: usize> {
1367    pub len: usize,
1368    pub bytes: [u8; CAP],
1369}
1370
1371impl<const CAP: usize> EvmCdBytes<CAP> {
1372    pub const fn new() -> Self {
1373        Self {
1374            len: 0,
1375            bytes: [0; CAP],
1376        }
1377    }
1378
1379    pub fn try_from_slice(value: &[u8]) -> Result<Self, EvmCdBytesError> {
1380        if value.len() > CAP {
1381            return Err(EvmCdBytesError::TooLong);
1382        }
1383        let mut bytes = [0; CAP];
1384        bytes[..value.len()].copy_from_slice(value);
1385        Ok(Self {
1386            len: value.len(),
1387            bytes,
1388        })
1389    }
1390
1391    pub fn try_from_serialised<T: EvmCdSerialise + ?Sized>(value: &T) -> Result<Self, Error> {
1392        let mut bytes = Self::new();
1393        value.serialise(&mut bytes)?;
1394        Ok(bytes)
1395    }
1396
1397    pub const fn len(&self) -> usize {
1398        self.len
1399    }
1400
1401    pub const fn is_empty(&self) -> bool {
1402        self.len == 0
1403    }
1404
1405    pub const fn capacity(&self) -> usize {
1406        CAP
1407    }
1408
1409    pub fn as_slice(&self) -> &[u8] {
1410        &self.bytes[..self.len]
1411    }
1412
1413    pub fn clear(&mut self) {
1414        self.len = 0;
1415    }
1416
1417    pub fn extend_from_slice(&mut self, value: &[u8]) -> Result<(), EvmCdBytesError> {
1418        let end = self
1419            .len
1420            .checked_add(value.len())
1421            .filter(|end| *end <= CAP)
1422            .ok_or(EvmCdBytesError::TooLong)?;
1423        self.bytes[self.len..end].copy_from_slice(value);
1424        self.len = end;
1425        Ok(())
1426    }
1427}
1428
1429impl<const CAP: usize> Default for EvmCdBytes<CAP> {
1430    fn default() -> Self {
1431        Self::new()
1432    }
1433}
1434
1435impl<const CAP: usize> From<[u8; CAP]> for EvmCdBytes<CAP> {
1436    fn from(bytes: [u8; CAP]) -> Self {
1437        Self { len: CAP, bytes }
1438    }
1439}
1440
1441impl<const CAP: usize> TryFrom<&[u8]> for EvmCdBytes<CAP> {
1442    type Error = EvmCdBytesError;
1443
1444    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
1445        Self::try_from_slice(value)
1446    }
1447}
1448
1449#[cfg(feature = "alloc")]
1450impl<const CAP: usize> TryFrom<Vec<u8>> for EvmCdBytes<CAP> {
1451    type Error = EvmCdBytesError;
1452
1453    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
1454        Self::try_from_slice(&value)
1455    }
1456}
1457
1458impl<const CAP: usize> AsRef<[u8]> for EvmCdBytes<CAP> {
1459    fn as_ref(&self) -> &[u8] {
1460        self.as_slice()
1461    }
1462}
1463
1464impl<const CAP: usize> core::fmt::Debug for EvmCdBytes<CAP> {
1465    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1466        core::fmt::Debug::fmt(self.as_slice(), formatter)
1467    }
1468}
1469
1470impl<const CAP: usize> PartialEq for EvmCdBytes<CAP> {
1471    fn eq(&self, other: &Self) -> bool {
1472        self.as_slice() == other.as_slice()
1473    }
1474}
1475
1476impl<const CAP: usize> Eq for EvmCdBytes<CAP> {}
1477
1478impl<const CAP: usize> PartialOrd for EvmCdBytes<CAP> {
1479    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1480        Some(self.cmp(other))
1481    }
1482}
1483
1484impl<const CAP: usize> Ord for EvmCdBytes<CAP> {
1485    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1486        self.as_slice().cmp(other.as_slice())
1487    }
1488}
1489
1490impl<const CAP: usize> core::hash::Hash for EvmCdBytes<CAP> {
1491    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1492        core::hash::Hash::hash(self.as_slice(), state)
1493    }
1494}
1495
1496#[doc(hidden)]
1497pub struct EvmCdBytesWriter<'a, const CAP: usize> {
1498    pub bytes: &'a mut EvmCdBytes<CAP>,
1499}
1500
1501#[cfg(not(feature = "std"))]
1502impl<const CAP: usize> Write for EvmCdBytesWriter<'_, CAP> {
1503    fn write(&mut self, value: &[u8]) -> Result<usize, Error> {
1504        let written = core::cmp::min(CAP - self.bytes.len, value.len());
1505        let end = self.bytes.len + written;
1506        self.bytes.bytes[self.bytes.len..end].copy_from_slice(&value[..written]);
1507        self.bytes.len = end;
1508        Ok(written)
1509    }
1510
1511    fn flush(&mut self) -> Result<(), Error> {
1512        Ok(())
1513    }
1514
1515    fn is_empty(&self) -> bool {
1516        self.bytes.len == CAP
1517    }
1518}
1519
1520#[cfg(feature = "std")]
1521impl<const CAP: usize> Write for EvmCdBytesWriter<'_, CAP> {
1522    fn write(&mut self, value: &[u8]) -> Result<usize, Error> {
1523        let written = core::cmp::min(CAP - self.bytes.len, value.len());
1524        let end = self.bytes.len + written;
1525        self.bytes.bytes[self.bytes.len..end].copy_from_slice(&value[..written]);
1526        self.bytes.len = end;
1527        Ok(written)
1528    }
1529
1530    fn flush(&mut self) -> Result<(), Error> {
1531        Ok(())
1532    }
1533}
1534
1535impl<const CAP: usize> EvmCdWriteTarget for EvmCdBytes<CAP> {
1536    type Writer<'a> = EvmCdBytesWriter<'a, CAP>;
1537
1538    fn writer(&mut self) -> Self::Writer<'_> {
1539        EvmCdBytesWriter { bytes: self }
1540    }
1541}
1542
1543impl<const CAP: usize> EvmCdSerialise for EvmCdBytes<CAP> {
1544    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1545        write_dynamic_bytes(self.as_slice(), writer)
1546    }
1547
1548    fn is_abi_dynamic() -> bool {
1549        true
1550    }
1551
1552    fn abi_tail_size(&self) -> usize {
1553        dynamic_tail_size(self.len)
1554    }
1555
1556    fn serialise_abi_head<W: Write>(
1557        &self,
1558        tail_offset: usize,
1559        writer: &mut W,
1560    ) -> Result<(), Error> {
1561        U::from_usize(tail_offset).serialise_value(writer)
1562    }
1563
1564    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1565        write_dynamic_tail(self.as_slice(), writer)
1566    }
1567
1568    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1569        hasher.update(b"bytes")
1570    }
1571}
1572
1573impl<const CAP: usize> EvmCdDeserialise for EvmCdBytes<CAP> {
1574    type Buffer = EvmCdBuffer<([u8; 64], [u8; CAP], [u8; 31])>;
1575
1576    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1577        let (bytes, len) = read_dynamic_bytes::<CAP, _>(reader)?;
1578        Ok(Self { len, bytes })
1579    }
1580
1581    fn is_abi_dynamic() -> bool {
1582        true
1583    }
1584
1585    fn abi_tail_size(&self) -> usize {
1586        dynamic_tail_size(self.len)
1587    }
1588
1589    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1590        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1591    }
1592
1593    fn deserialise_abi_finish<R: Read>(
1594        head: EvmCdHead<Self>,
1595        expected_tail_offset: usize,
1596        reader: &mut R,
1597    ) -> Result<Self, Error> {
1598        match head {
1599            EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1600                let (bytes, len) = read_dynamic_tail::<CAP, _>(reader)?;
1601                Ok(Self { len, bytes })
1602            }
1603            _ => Err(invalid_data()),
1604        }
1605    }
1606
1607    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1608        hasher.update(b"bytes")
1609    }
1610}
1611
1612#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1613pub enum EvmCdStringError {
1614    InvalidBounds,
1615    TooShort,
1616    TooLong,
1617}
1618
1619#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1620pub struct EvmCdString<const MIN: usize, const CAP: usize> {
1621    pub len: usize,
1622    pub bytes: [u8; CAP],
1623}
1624
1625impl<const MIN: usize, const CAP: usize> EvmCdString<MIN, CAP> {
1626    pub fn try_from_str(value: &str) -> Result<Self, EvmCdStringError> {
1627        if MIN > CAP {
1628            return Err(EvmCdStringError::InvalidBounds);
1629        }
1630        if value.len() < MIN {
1631            return Err(EvmCdStringError::TooShort);
1632        }
1633        if value.len() > CAP {
1634            return Err(EvmCdStringError::TooLong);
1635        }
1636        let mut bytes = [0u8; CAP];
1637        bytes[..value.len()].copy_from_slice(value.as_bytes());
1638        Ok(Self {
1639            len: value.len(),
1640            bytes,
1641        })
1642    }
1643
1644    pub const fn len(&self) -> usize {
1645        self.len
1646    }
1647
1648    pub const fn is_empty(&self) -> bool {
1649        self.len == 0
1650    }
1651
1652    pub const fn capacity(&self) -> usize {
1653        CAP
1654    }
1655
1656    pub fn as_bytes(&self) -> &[u8] {
1657        &self.bytes[..self.len]
1658    }
1659
1660    pub fn as_str(&self) -> &str {
1661        // SAFETY: constructors and deserialisation validate UTF-8, and no API
1662        // exposes mutable access to the initialized bytes.
1663        unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
1664    }
1665}
1666
1667impl<const MIN: usize, const CAP: usize> TryFrom<&str> for EvmCdString<MIN, CAP> {
1668    type Error = EvmCdStringError;
1669
1670    fn try_from(value: &str) -> Result<Self, Self::Error> {
1671        Self::try_from_str(value)
1672    }
1673}
1674
1675impl<const MIN: usize, const CAP: usize> AsRef<str> for EvmCdString<MIN, CAP> {
1676    fn as_ref(&self) -> &str {
1677        self.as_str()
1678    }
1679}
1680
1681impl<const MIN: usize, const CAP: usize> AsRef<[u8]> for EvmCdString<MIN, CAP> {
1682    fn as_ref(&self) -> &[u8] {
1683        self.as_bytes()
1684    }
1685}
1686
1687impl<const MIN: usize, const CAP: usize> core::borrow::Borrow<str> for EvmCdString<MIN, CAP> {
1688    fn borrow(&self) -> &str {
1689        self.as_str()
1690    }
1691}
1692
1693impl<const MIN: usize, const CAP: usize> core::fmt::Display for EvmCdString<MIN, CAP> {
1694    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1695        formatter.write_str(self.as_str())
1696    }
1697}
1698
1699impl<const MIN: usize, const CAP: usize> core::fmt::Debug for EvmCdString<MIN, CAP> {
1700    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1701        core::fmt::Debug::fmt(self.as_str(), formatter)
1702    }
1703}
1704
1705impl<const MIN: usize, const CAP: usize> core::str::FromStr for EvmCdString<MIN, CAP> {
1706    type Err = EvmCdStringError;
1707
1708    fn from_str(value: &str) -> Result<Self, Self::Err> {
1709        Self::try_from_str(value)
1710    }
1711}
1712
1713impl<const MIN: usize, const CAP: usize> EvmCdSerialise for EvmCdString<MIN, CAP> {
1714    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1715        write_dynamic_bytes(self.as_bytes(), writer)
1716    }
1717
1718    fn is_abi_dynamic() -> bool {
1719        true
1720    }
1721
1722    fn abi_tail_size(&self) -> usize {
1723        dynamic_tail_size(self.len)
1724    }
1725
1726    fn serialise_abi_head<W: Write>(
1727        &self,
1728        tail_offset: usize,
1729        writer: &mut W,
1730    ) -> Result<(), Error> {
1731        U::from_usize(tail_offset).serialise_value(writer)
1732    }
1733
1734    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1735        write_dynamic_tail(self.as_bytes(), writer)
1736    }
1737
1738    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1739        hasher.update(b"string")
1740    }
1741}
1742
1743impl<const MIN: usize, const CAP: usize> EvmCdDeserialise for EvmCdString<MIN, CAP> {
1744    type Buffer = EvmCdBuffer<([u8; 64], [u8; CAP], [u8; 31])>;
1745
1746    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1747        if MIN > CAP {
1748            return Err(invalid_data());
1749        }
1750        let (bytes, len) = read_dynamic_bytes::<CAP, _>(reader)?;
1751        if len < MIN || core::str::from_utf8(&bytes[..len]).is_err() {
1752            return Err(invalid_data());
1753        }
1754        Ok(Self { len, bytes })
1755    }
1756
1757    fn is_abi_dynamic() -> bool {
1758        true
1759    }
1760
1761    fn abi_tail_size(&self) -> usize {
1762        dynamic_tail_size(self.len)
1763    }
1764
1765    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
1766        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
1767    }
1768
1769    fn deserialise_abi_finish<R: Read>(
1770        head: EvmCdHead<Self>,
1771        expected_tail_offset: usize,
1772        reader: &mut R,
1773    ) -> Result<Self, Error> {
1774        match head {
1775            EvmCdHead::Offset(offset) if offset == expected_tail_offset => {
1776                if MIN > CAP {
1777                    return Err(invalid_data());
1778                }
1779                let (bytes, len) = read_dynamic_tail::<CAP, _>(reader)?;
1780                if len < MIN || core::str::from_utf8(&bytes[..len]).is_err() {
1781                    return Err(invalid_data());
1782                }
1783                Ok(Self { len, bytes })
1784            }
1785            _ => Err(invalid_data()),
1786        }
1787    }
1788
1789    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1790        hasher.update(b"string")
1791    }
1792}
1793
1794#[cfg(feature = "alloc")]
1795impl<const MIN: usize, const CAP: usize> From<EvmCdString<MIN, CAP>> for String {
1796    fn from(value: EvmCdString<MIN, CAP>) -> Self {
1797        String::from(value.as_str())
1798    }
1799}
1800
1801#[cfg(feature = "alloc")]
1802fn vec_is_bytes<T: 'static>() -> bool {
1803    core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>()
1804}
1805
1806#[cfg(feature = "alloc")]
1807fn vec_as_bytes<T: 'static>(values: &[T]) -> &[u8] {
1808    debug_assert!(vec_is_bytes::<T>());
1809    // SAFETY: this helper is called only when TypeId proves that T is u8.
1810    unsafe { core::slice::from_raw_parts(values.as_ptr().cast::<u8>(), values.len()) }
1811}
1812
1813#[cfg(feature = "alloc")]
1814impl<T> EvmCdSerialise for Vec<T>
1815where
1816    T: EvmCdSerialise + 'static,
1817{
1818    fn serialise_writer<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1819        U::from_u32(32).serialise_value(writer)?;
1820        self.serialise_abi_tail(writer)
1821    }
1822
1823    fn is_abi_dynamic() -> bool {
1824        true
1825    }
1826
1827    fn abi_tail_size(&self) -> usize {
1828        if vec_is_bytes::<T>() {
1829            dynamic_tail_size(self.len())
1830        } else {
1831            self.len()
1832                .saturating_mul(T::abi_head_size())
1833                .saturating_add(32)
1834                .saturating_add(self.iter().fold(0usize, |size, value| {
1835                    size.saturating_add(value.abi_tail_size())
1836                }))
1837        }
1838    }
1839
1840    fn serialise_abi_head<W: Write>(
1841        &self,
1842        tail_offset: usize,
1843        writer: &mut W,
1844    ) -> Result<(), Error> {
1845        U::from_usize(tail_offset).serialise_value(writer)
1846    }
1847
1848    fn serialise_abi_tail<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
1849        if vec_is_bytes::<T>() {
1850            return write_dynamic_tail(vec_as_bytes(self), writer);
1851        }
1852
1853        U::from_usize(self.len()).serialise_value(writer)?;
1854        let mut tail_offset = self
1855            .len()
1856            .checked_mul(T::abi_head_size())
1857            .ok_or_else(invalid_data)?;
1858        for value in self {
1859            value.serialise_abi_head(tail_offset, writer)?;
1860            tail_offset = tail_offset
1861                .checked_add(value.abi_tail_size())
1862                .ok_or_else(invalid_data)?;
1863        }
1864        for value in self {
1865            value.serialise_abi_tail(writer)?;
1866        }
1867        Ok(())
1868    }
1869
1870    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
1871        if vec_is_bytes::<T>() {
1872            hasher.update(b"bytes")
1873        } else {
1874            T::append_abi_type(hasher).update(b"[]")
1875        }
1876    }
1877}
1878
1879#[cfg(feature = "alloc")]
1880const MAX_ALLOC_DESERIALISE_LEN: usize = 16 * 1024 * 1024;
1881
1882#[cfg(feature = "alloc")]
1883fn read_vec_bytes_tail<R: Read>(reader: &mut R) -> Result<Vec<u8>, Error> {
1884    let len = read_usize_word(reader)?;
1885    if len > MAX_ALLOC_DESERIALISE_LEN {
1886        return Err(invalid_data());
1887    }
1888    let mut out = Vec::new();
1889    out.try_reserve_exact(len).map_err(|_| invalid_data())?;
1890    out.resize(len, 0);
1891    reader.read_exact(&mut out)?;
1892    let padding = (32 - len % 32) % 32;
1893    let mut padding_bytes = [0u8; 31];
1894    reader.read_exact(&mut padding_bytes[..padding])?;
1895    if padding_bytes[..padding].iter().any(|byte| *byte != 0) {
1896        return Err(invalid_data());
1897    }
1898    Ok(out)
1899}
1900
1901#[cfg(feature = "alloc")]
1902fn bytes_into_vec<T: 'static>(bytes: Vec<u8>) -> Vec<T> {
1903    debug_assert!(vec_is_bytes::<T>());
1904    let mut bytes = core::mem::ManuallyDrop::new(bytes);
1905    // SAFETY: TypeId proves that T is u8, so the allocation layout and elements match.
1906    unsafe {
1907        Vec::from_raw_parts(
1908            bytes.as_mut_ptr().cast::<T>(),
1909            bytes.len(),
1910            bytes.capacity(),
1911        )
1912    }
1913}
1914
1915#[cfg(feature = "alloc")]
1916fn validate_vec_array_len<T: EvmCdDeserialise>(len: usize) -> Result<(), Error> {
1917    let head_bytes = len
1918        .checked_mul(T::abi_head_size())
1919        .ok_or_else(invalid_data)?;
1920    let value_bytes = len
1921        .checked_mul(core::mem::size_of::<T>())
1922        .ok_or_else(invalid_data)?;
1923    let offset_bytes = if T::is_abi_dynamic() {
1924        len.checked_mul(core::mem::size_of::<usize>())
1925            .ok_or_else(invalid_data)?
1926    } else {
1927        0
1928    };
1929    if head_bytes > MAX_ALLOC_DESERIALISE_LEN
1930        || value_bytes > MAX_ALLOC_DESERIALISE_LEN
1931        || offset_bytes > MAX_ALLOC_DESERIALISE_LEN
1932    {
1933        return Err(invalid_data());
1934    }
1935    Ok(())
1936}
1937
1938#[cfg(feature = "alloc")]
1939fn read_vec_array_tail<T, R>(reader: &mut R) -> Result<Vec<T>, Error>
1940where
1941    T: EvmCdDeserialise + 'static,
1942    R: Read,
1943{
1944    let len = read_usize_word(reader)?;
1945    validate_vec_array_len::<T>(len)?;
1946
1947    let mut out = Vec::new();
1948    out.try_reserve_exact(len).map_err(|_| invalid_data())?;
1949    if T::is_abi_dynamic() {
1950        let mut offsets = Vec::new();
1951        offsets.try_reserve_exact(len).map_err(|_| invalid_data())?;
1952        for _ in 0..len {
1953            match T::deserialise_abi_head(reader)? {
1954                EvmCdHead::Offset(offset) => offsets.push(offset),
1955                EvmCdHead::Value(_) => return Err(invalid_data()),
1956            }
1957        }
1958        let mut expected_tail_offset = len
1959            .checked_mul(T::abi_head_size())
1960            .ok_or_else(invalid_data)?;
1961        for offset in offsets {
1962            let value =
1963                T::deserialise_abi_finish(EvmCdHead::Offset(offset), expected_tail_offset, reader)?;
1964            expected_tail_offset = expected_tail_offset
1965                .checked_add(value.abi_tail_size())
1966                .ok_or_else(invalid_data)?;
1967            out.push(value);
1968        }
1969    } else {
1970        for _ in 0..len {
1971            let head = T::deserialise_abi_head(reader)?;
1972            out.push(T::deserialise_abi_finish(head, 0, reader)?);
1973        }
1974    }
1975    Ok(out)
1976}
1977
1978#[cfg(feature = "alloc")]
1979fn read_vec_tail<T, R>(reader: &mut R) -> Result<Vec<T>, Error>
1980where
1981    T: EvmCdDeserialise + 'static,
1982    R: Read,
1983{
1984    if vec_is_bytes::<T>() {
1985        read_vec_bytes_tail(reader).map(bytes_into_vec)
1986    } else {
1987        read_vec_array_tail(reader)
1988    }
1989}
1990
1991#[cfg(feature = "alloc")]
1992impl<T> EvmCdDeserialise for Vec<T>
1993where
1994    T: EvmCdDeserialise + 'static,
1995{
1996    type Buffer = EvmCdDynamicBuffer<()>;
1997
1998    fn deserialise_reader<R: Read>(reader: &mut R) -> Result<Self, Error> {
1999        if read_usize_word(reader)? != 32 {
2000            return Err(invalid_data());
2001        }
2002        read_vec_tail(reader)
2003    }
2004
2005    fn is_abi_dynamic() -> bool {
2006        true
2007    }
2008
2009    fn abi_tail_size(&self) -> usize {
2010        if vec_is_bytes::<T>() {
2011            dynamic_tail_size(self.len())
2012        } else {
2013            self.len()
2014                .saturating_mul(T::abi_head_size())
2015                .saturating_add(32)
2016                .saturating_add(self.iter().fold(0usize, |size, value| {
2017                    size.saturating_add(value.abi_tail_size())
2018                }))
2019        }
2020    }
2021
2022    fn deserialise_abi_head<R: Read>(reader: &mut R) -> Result<EvmCdHead<Self>, Error> {
2023        Ok(EvmCdHead::Offset(read_usize_word(reader)?))
2024    }
2025
2026    fn deserialise_abi_finish<R: Read>(
2027        head: EvmCdHead<Self>,
2028        expected_tail_offset: usize,
2029        reader: &mut R,
2030    ) -> Result<Self, Error> {
2031        match head {
2032            EvmCdHead::Offset(offset) if offset == expected_tail_offset => read_vec_tail(reader),
2033            _ => Err(invalid_data()),
2034        }
2035    }
2036
2037    fn append_abi_type(hasher: SelectorHasher) -> SelectorHasher {
2038        if vec_is_bytes::<T>() {
2039            hasher.update(b"bytes")
2040        } else {
2041            T::append_abi_type(hasher).update(b"[]")
2042        }
2043    }
2044}
2045
2046#[cfg(all(test, not(feature = "std")))]
2047mod tests {
2048    use super::{EvmCdDeserialise, EvmCdSerialise};
2049
2050    #[derive(
2051        Debug, PartialEq, Eq, bobcat_cd_derive::EvmCdSerialise, bobcat_cd_derive::EvmCdDeserialise,
2052    )]
2053    struct SliceValue {
2054        small: u8,
2055        large: u32,
2056    }
2057
2058    #[test]
2059    fn mutable_slice_is_a_serialisation_writer_and_deserialisation_reader() {
2060        let value = SliceValue {
2061            small: 7,
2062            large: 0x1234_5678,
2063        };
2064        let mut storage = [0u8; 64];
2065
2066        let mut writer = storage.as_mut_slice();
2067        value.serialise(&mut writer).unwrap();
2068        assert!(writer.is_empty());
2069
2070        let mut reader = storage.as_mut_slice();
2071        assert_eq!(SliceValue::deserialise_reader(&mut reader).unwrap(), value);
2072        assert!(reader.is_empty());
2073    }
2074}