fuel_types/
canonical.rs

1//! Canonical serialization and deserialization of Fuel types.
2//!
3//! This module provides the `Serialize` and `Deserialize` traits, which
4//! allow for automatic serialization and deserialization of Fuel types.
5
6#![allow(unsafe_code)]
7
8#[cfg(feature = "alloc")]
9use alloc::vec::Vec;
10use core::fmt;
11
12use core::mem::MaybeUninit;
13pub use fuel_derive::{
14    Deserialize,
15    Serialize,
16};
17
18/// Error when serializing or deserializing.
19#[derive(Debug, Eq, PartialEq)]
20#[non_exhaustive]
21pub enum Error {
22    /// The buffer is to short for writing or reading.
23    BufferIsTooShort,
24    /// Got unknown enum's discriminant.
25    UnknownDiscriminant,
26    /// Struct prefix (set with `#[canonical(prefix = ...)]`) was invalid.
27    InvalidPrefix,
28    /// Allocation too large to be correct.
29    AllocationLimit,
30    /// Unknown error.
31    Unknown(&'static str),
32}
33
34impl Error {
35    pub(crate) fn as_str(&self) -> &'static str {
36        match self {
37            Error::BufferIsTooShort => "buffer is too short",
38            Error::UnknownDiscriminant => "unknown discriminant",
39            Error::InvalidPrefix => {
40                "prefix set with #[canonical(prefix = ...)] was invalid"
41            }
42            Error::AllocationLimit => "allocation too large",
43            Error::Unknown(str) => str,
44        }
45    }
46}
47
48impl fmt::Display for Error {
49    /// Shows a human-readable description of the `Error`.
50    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
51        fmt.write_str(self.as_str())
52    }
53}
54
55/// Allows writing of data.
56pub trait Output {
57    /// Write bytes to the output buffer.
58    fn write(&mut self, bytes: &[u8]) -> Result<(), Error>;
59
60    /// Write a single byte to the output buffer.
61    fn push_byte(&mut self, byte: u8) -> Result<(), Error> {
62        self.write(&[byte])
63    }
64}
65
66/// Allows serialize the type into the `Output`.
67/// https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/tx_format.md#transaction
68pub trait Serialize {
69    /// !INTERNAL USAGE ONLY!
70    /// Array of bytes that are now aligned by themselves.
71    #[doc(hidden)]
72    const UNALIGNED_BYTES: bool = false;
73
74    /// Size of the static part of the serialized object, in bytes.
75    /// Saturates to usize::MAX on overflow.
76    fn size_static(&self) -> usize;
77
78    /// Size of the dynamic part, in bytes.
79    /// Saturates to usize::MAX on overflow.
80    fn size_dynamic(&self) -> usize;
81
82    /// Total size of the serialized object, in bytes.
83    /// Saturates to usize::MAX on overflow.
84    fn size(&self) -> usize {
85        self.size_static().saturating_add(self.size_dynamic())
86    }
87
88    /// Encodes `Self` into the `buffer`.
89    ///
90    /// It is better to not implement this function directly, instead implement
91    /// `encode_static` and `encode_dynamic`.
92    fn encode<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
93        self.encode_static(buffer)?;
94        self.encode_dynamic(buffer)
95    }
96
97    /// Encodes staticly-sized part of `Self`.
98    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error>;
99
100    /// Encodes dynamically-sized part of `Self`.
101    /// The default implementation does nothing. Dynamically-sized contains should
102    /// override this.
103    fn encode_dynamic<O: Output + ?Sized>(&self, _buffer: &mut O) -> Result<(), Error> {
104        Ok(())
105    }
106
107    /// Encodes `Self` into bytes vector. Required known size.
108    #[cfg(feature = "alloc")]
109    fn to_bytes(&self) -> Vec<u8> {
110        let mut vec = Vec::with_capacity(self.size());
111        self.encode(&mut vec).expect("Unable to encode self");
112        vec
113    }
114}
115
116/// Allows reading of data into a slice.
117pub trait Input {
118    /// Returns the remaining length of the input data.
119    fn remaining(&mut self) -> usize;
120
121    /// Peek the exact number of bytes required to fill the given buffer.
122    fn peek(&self, buf: &mut [u8]) -> Result<(), Error>;
123
124    /// Read the exact number of bytes required to fill the given buffer.
125    fn read(&mut self, buf: &mut [u8]) -> Result<(), Error>;
126
127    /// Peek a single byte from the input.
128    fn peek_byte(&mut self) -> Result<u8, Error> {
129        let mut buf = [0u8];
130        self.peek(&mut buf[..])?;
131        Ok(buf[0])
132    }
133
134    /// Read a single byte from the input.
135    fn read_byte(&mut self) -> Result<u8, Error> {
136        let mut buf = [0u8];
137        self.read(&mut buf[..])?;
138        Ok(buf[0])
139    }
140
141    /// Skips next `n` bytes.
142    fn skip(&mut self, n: usize) -> Result<(), Error>;
143}
144
145/// Allows deserialize the type from the `Input`.
146/// https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/tx_format.md#transaction
147pub trait Deserialize: Sized {
148    /// !INTERNAL USAGE ONLY!
149    /// Array of bytes that are now aligned by themselves.
150    #[doc(hidden)]
151    const UNALIGNED_BYTES: bool = false;
152
153    /// Decodes `Self` from the `buffer`.
154    ///
155    /// It is better to not implement this function directly, instead implement
156    /// `decode_static` and `decode_dynamic`.
157    fn decode<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
158        let mut object = Self::decode_static(buffer)?;
159        object.decode_dynamic(buffer)?;
160        Ok(object)
161    }
162
163    /// Decodes static part of `Self` from the `buffer`.
164    fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error>;
165
166    /// Decodes dynamic part of the information from the `buffer` to fill `Self`.
167    /// The default implementation does nothing. Dynamically-sized contains should
168    /// override this.
169    fn decode_dynamic<I: Input + ?Sized>(
170        &mut self,
171        _buffer: &mut I,
172    ) -> Result<(), Error> {
173        Ok(())
174    }
175
176    /// Helper method for deserializing `Self` from bytes.
177    fn from_bytes(mut buffer: &[u8]) -> Result<Self, Error> {
178        Self::decode(&mut buffer)
179    }
180}
181
182/// The data of each field should be aligned to 64 bits.
183pub const ALIGN: usize = 8;
184
185/// The number of padding bytes required to align the given length correctly.
186#[allow(clippy::arithmetic_side_effects)] // Safety: (a % b) < b
187const fn alignment_bytes(len: usize) -> usize {
188    let modulo = len % ALIGN;
189    if modulo == 0 {
190        0
191    } else {
192        ALIGN - modulo
193    }
194}
195
196/// Size after alignment. Saturates on overflow.
197pub const fn aligned_size(len: usize) -> usize {
198    len.saturating_add(alignment_bytes(len))
199}
200
201macro_rules! impl_for_primitives {
202    ($t:ident, $unpadded:literal) => {
203        impl Serialize for $t {
204            const UNALIGNED_BYTES: bool = $unpadded;
205
206            #[inline(always)]
207            fn size_static(&self) -> usize {
208                aligned_size(::core::mem::size_of::<$t>())
209            }
210
211            #[inline(always)]
212            fn size_dynamic(&self) -> usize {
213                0
214            }
215
216            #[inline(always)]
217            fn encode_static<O: Output + ?Sized>(
218                &self,
219                buffer: &mut O,
220            ) -> Result<(), Error> {
221                // Primitive types are zero-padded on left side to a 8-byte boundary.
222                // The resulting value is always well-aligned.
223                let bytes = <$t>::to_be_bytes(*self);
224                for _ in 0..alignment_bytes(bytes.len()) {
225                    // Zero-pad
226                    buffer.push_byte(0)?;
227                }
228                buffer.write(bytes.as_ref())?;
229                Ok(())
230            }
231        }
232
233        impl Deserialize for $t {
234            const UNALIGNED_BYTES: bool = $unpadded;
235
236            fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
237                let mut asset = [0u8; ::core::mem::size_of::<$t>()];
238                buffer.skip(alignment_bytes(asset.len()))?; // Skip zero-padding
239                buffer.read(asset.as_mut())?;
240                Ok(<$t>::from_be_bytes(asset))
241            }
242        }
243    };
244}
245
246impl_for_primitives!(u8, true);
247impl_for_primitives!(u16, false);
248impl_for_primitives!(u32, false);
249impl_for_primitives!(usize, false);
250impl_for_primitives!(u64, false);
251impl_for_primitives!(u128, false);
252
253// Empty tuple `()`, i.e. the unit type takes up no space.
254impl Serialize for () {
255    fn size_static(&self) -> usize {
256        0
257    }
258
259    #[inline(always)]
260    fn size_dynamic(&self) -> usize {
261        0
262    }
263
264    #[inline(always)]
265    fn encode_static<O: Output + ?Sized>(&self, _buffer: &mut O) -> Result<(), Error> {
266        Ok(())
267    }
268}
269
270impl Deserialize for () {
271    fn decode_static<I: Input + ?Sized>(_buffer: &mut I) -> Result<Self, Error> {
272        Ok(())
273    }
274}
275
276/// To protect against malicious large inputs, vector size is limited when decoding.
277pub const VEC_DECODE_LIMIT: usize = 100 * (1 << 20); // 100 MiB
278
279#[cfg(feature = "alloc")]
280impl<T: Serialize> Serialize for Vec<T> {
281    fn size_static(&self) -> usize {
282        8
283    }
284
285    #[inline(always)]
286    fn size_dynamic(&self) -> usize {
287        if T::UNALIGNED_BYTES {
288            aligned_size(self.len())
289        } else {
290            aligned_size(
291                self.iter()
292                    .map(|e| e.size())
293                    .reduce(usize::saturating_add)
294                    .unwrap_or_default(),
295            )
296        }
297    }
298
299    #[inline(always)]
300    // Encode only the size of the vector. Elements will be encoded in the
301    // `encode_dynamic` method.
302    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
303        if self.len() > VEC_DECODE_LIMIT {
304            return Err(Error::AllocationLimit)
305        }
306        let len: u64 = self.len().try_into().expect("msg.len() > u64::MAX");
307        len.encode(buffer)
308    }
309
310    fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
311        // Bytes - Vec<u8> it a separate case without padding for each element.
312        // It should padded at the end if is not % ALIGN
313        if T::UNALIGNED_BYTES {
314            // SAFETY: `UNALIGNED_BYTES` only set for `u8`.
315            let bytes = unsafe { ::core::mem::transmute::<&Vec<T>, &Vec<u8>>(self) };
316            buffer.write(bytes.as_slice())?;
317            for _ in 0..alignment_bytes(self.len()) {
318                buffer.push_byte(0)?;
319            }
320        } else {
321            for e in self.iter() {
322                e.encode(buffer)?;
323            }
324        }
325        Ok(())
326    }
327}
328
329#[cfg(feature = "alloc")]
330impl<T: Deserialize> Deserialize for Vec<T> {
331    // Decode only the capacity of the vector. Elements will be decoded in the
332    // `decode_dynamic` method. The capacity is needed for iteration there.
333    fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
334        let cap = u64::decode(buffer)?;
335        let cap: usize = cap.try_into().map_err(|_| Error::AllocationLimit)?;
336        if cap > VEC_DECODE_LIMIT {
337            return Err(Error::AllocationLimit)
338        }
339        Ok(Vec::with_capacity(cap))
340    }
341
342    fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
343        for _ in 0..self.capacity() {
344            // Bytes - Vec<u8> it a separate case without unpadding for each element.
345            // It should unpadded at the end if is not % ALIGN
346            if T::UNALIGNED_BYTES {
347                let byte = buffer.read_byte()?;
348                // SAFETY: `UNALIGNED_BYTES` implemented set for `u8`.
349                let _self =
350                    unsafe { ::core::mem::transmute::<&mut Vec<T>, &mut Vec<u8>>(self) };
351                _self.push(byte);
352            } else {
353                self.push(T::decode(buffer)?);
354            }
355        }
356
357        if T::UNALIGNED_BYTES {
358            buffer.skip(alignment_bytes(self.capacity()))?;
359        }
360
361        Ok(())
362    }
363}
364
365impl<const N: usize, T: Serialize> Serialize for [T; N] {
366    fn size_static(&self) -> usize {
367        if T::UNALIGNED_BYTES {
368            aligned_size(N)
369        } else {
370            aligned_size(
371                self.iter()
372                    .map(|e| e.size_static())
373                    .reduce(usize::saturating_add)
374                    .unwrap_or_default(),
375            )
376        }
377    }
378
379    #[inline(always)]
380    fn size_dynamic(&self) -> usize {
381        if T::UNALIGNED_BYTES {
382            0
383        } else {
384            aligned_size(
385                self.iter()
386                    .map(|e| e.size_dynamic())
387                    .reduce(usize::saturating_add)
388                    .unwrap_or_default(),
389            )
390        }
391    }
392
393    #[inline(always)]
394    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
395        // Bytes - [u8; N] it a separate case without padding for each element.
396        // It should padded at the end if is not % ALIGN
397        if T::UNALIGNED_BYTES {
398            // SAFETY: `Type::U8` implemented only for `u8`.
399            let bytes = unsafe { ::core::mem::transmute::<&[T; N], &[u8; N]>(self) };
400            buffer.write(bytes.as_slice())?;
401            for _ in 0..alignment_bytes(N) {
402                buffer.push_byte(0)?;
403            }
404        } else {
405            for e in self.iter() {
406                e.encode_static(buffer)?;
407            }
408        }
409        Ok(())
410    }
411
412    fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
413        for e in self.iter() {
414            e.encode_dynamic(buffer)?;
415        }
416
417        Ok(())
418    }
419}
420
421impl<const N: usize, T: Deserialize> Deserialize for [T; N] {
422    fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
423        if T::UNALIGNED_BYTES {
424            let mut bytes: [u8; N] = [0; N];
425            buffer.read(bytes.as_mut())?;
426            buffer.skip(alignment_bytes(N))?;
427            let ref_typed: &[T; N] = unsafe { core::mem::transmute(&bytes) };
428            let typed: [T; N] = unsafe { core::ptr::read(ref_typed) };
429            Ok(typed)
430        } else {
431            // Spec doesn't say how to deserialize arrays with unaligned
432            // primitives(as `u16`, `u32`, `usize`), so unpad them.
433            // SAFETY: `uninit`` is an array of `MaybUninit`, which do not require
434            // initialization
435            let mut uninit: [MaybeUninit<T>; N] =
436                unsafe { MaybeUninit::uninit().assume_init() };
437            // The following line coerces the pointer to the array to a pointer
438            // to the first array element which is equivalent.
439            for i in 0..N {
440                match T::decode_static(buffer) {
441                    Err(e) => {
442                        for item in uninit.iter_mut().take(i) {
443                            // SAFETY: all elements up to index i (excluded have been
444                            // initialised)
445                            unsafe {
446                                item.assume_init_drop();
447                            }
448                        }
449                        return Err(e)
450                    }
451                    Ok(decoded) => {
452                        // SAFETY: `uninit[i]` is a MaybeUninit which can be
453                        // safely overwritten.
454                        uninit[i].write(decoded);
455
456                        // SAFETY: Point to the next element after every iteration.
457                        // 		 We do this N times therefore this is safe.
458                    }
459                }
460            }
461
462            // SAFETY: All array elements have been initialized above.
463            let init = uninit.map(|v| unsafe { v.assume_init() });
464            Ok(init)
465        }
466    }
467
468    fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
469        for e in self.iter_mut() {
470            e.decode_dynamic(buffer)?;
471        }
472        Ok(())
473    }
474}
475
476#[cfg(feature = "alloc")]
477impl Output for Vec<u8> {
478    fn write(&mut self, bytes: &[u8]) -> Result<(), Error> {
479        self.extend_from_slice(bytes);
480        Ok(())
481    }
482}
483
484impl Output for &'_ mut [u8] {
485    fn write(&mut self, from: &[u8]) -> Result<(), Error> {
486        if from.len() > self.len() {
487            return Err(Error::BufferIsTooShort)
488        }
489        let len = from.len();
490        self[..len].copy_from_slice(from);
491        // We need to reduce the inner slice by `len`, because we already filled them.
492        let reduced = &mut self[len..];
493
494        // Compiler is not clever enough to allow it.
495        // https://stackoverflow.com/questions/25730586/how-can-i-create-my-own-data-structure-with-an-iterator-that-returns-mutable-ref
496        *self = unsafe { &mut *(reduced as *mut [u8]) };
497        Ok(())
498    }
499}
500
501impl Input for &'_ [u8] {
502    fn remaining(&mut self) -> usize {
503        self.len()
504    }
505
506    fn peek(&self, into: &mut [u8]) -> Result<(), Error> {
507        if into.len() > self.len() {
508            return Err(Error::BufferIsTooShort)
509        }
510
511        let len = into.len();
512        into.copy_from_slice(&self[..len]);
513        Ok(())
514    }
515
516    fn read(&mut self, into: &mut [u8]) -> Result<(), Error> {
517        if into.len() > self.len() {
518            return Err(Error::BufferIsTooShort)
519        }
520
521        let len = into.len();
522        into.copy_from_slice(&self[..len]);
523        *self = &self[len..];
524        Ok(())
525    }
526
527    fn skip(&mut self, n: usize) -> Result<(), Error> {
528        if n > self.len() {
529            return Err(Error::BufferIsTooShort)
530        }
531
532        *self = &self[n..];
533        Ok(())
534    }
535}
536
537#[cfg(test)]
538mod tests {
539    use super::*;
540
541    fn validate<T: Serialize + Deserialize + Eq + core::fmt::Debug>(t: T) {
542        let bytes = t.to_bytes();
543        let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
544        assert_eq!(t, t2);
545        assert_eq!(t.to_bytes(), t2.to_bytes());
546
547        let mut vec = Vec::new();
548        t.encode_static(&mut vec).expect("Encode failed");
549        assert_eq!(vec.len(), t.size_static());
550    }
551
552    fn validate_enum<T: Serialize + Deserialize + Eq + fmt::Debug>(t: T) {
553        let bytes = t.to_bytes();
554        let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
555        assert_eq!(t, t2);
556        assert_eq!(t.to_bytes(), t2.to_bytes());
557
558        let mut vec = Vec::new();
559        t.encode_static(&mut vec).expect("Encode failed");
560        assert_eq!(vec.len(), t.size_static());
561        t.encode_dynamic(&mut vec).expect("Encode failed");
562        assert_eq!(vec.len(), t.size());
563
564        let mut vec2 = Vec::new();
565        t.encode_dynamic(&mut vec2).expect("Encode failed");
566        assert_eq!(vec2.len(), t.size_dynamic());
567    }
568
569    #[test]
570    fn test_canonical_encode_decode() {
571        validate(());
572        validate(123u8);
573        validate(u8::MAX);
574        validate(123u16);
575        validate(u16::MAX);
576        validate(123u32);
577        validate(u32::MAX);
578        validate(123u64);
579        validate(u64::MAX);
580        validate(123u128);
581        validate(u128::MAX);
582        validate(Vec::<u8>::new());
583        validate(Vec::<u16>::new());
584        validate(Vec::<u32>::new());
585        validate(Vec::<u64>::new());
586        validate(Vec::<u128>::new());
587        validate(vec![1u8]);
588        validate(vec![1u16]);
589        validate(vec![1u32]);
590        validate(vec![1u64]);
591        validate(vec![1u128]);
592        validate(vec![1u8, 2u8]);
593        validate(vec![1u16, 2u16]);
594        validate(vec![1u32, 2u32]);
595        validate(vec![1u64, 2u64]);
596        validate(vec![1u128, 2u128]);
597
598        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
599        struct TestStruct1 {
600            a: u8,
601            b: u16,
602        }
603
604        let t = TestStruct1 { a: 123, b: 456 };
605        assert_eq!(t.size_static(), 16);
606        assert_eq!(t.size(), 16);
607        validate(t);
608
609        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
610        struct TestStruct2 {
611            a: u8,
612            v: Vec<u8>,
613            b: u16,
614            arr0: [u8; 0],
615            arr1: [u8; 2],
616            arr2: [u16; 3],
617            arr3: [u64; 4],
618        }
619
620        validate(TestStruct2 {
621            a: 123,
622            v: vec![1, 2, 3],
623            b: 456,
624            arr0: [],
625            arr1: [1, 2],
626            arr2: [1, 2, u16::MAX],
627            arr3: [0, 3, 1111, u64::MAX],
628        });
629
630        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
631        #[repr(transparent)]
632        struct TestStruct3([u8; 64]);
633
634        let t = TestStruct3([1; 64]);
635        assert_eq!(t.size_static(), 64);
636        assert_eq!(t.size(), 64);
637        validate(t);
638
639        #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
640        #[canonical(prefix = 1u64)]
641        struct Prefixed1 {
642            a: [u8; 3],
643            b: Vec<u8>,
644        }
645        validate(Prefixed1 {
646            a: [1, 2, 3],
647            b: vec![4, 5, 6],
648        });
649
650        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
651        #[repr(u8)]
652        enum TestEnum1 {
653            A,
654            B,
655            C = 0x13,
656            D,
657        }
658
659        validate(TestEnum1::A);
660        validate(TestEnum1::B);
661        validate(TestEnum1::C);
662        validate(TestEnum1::D);
663
664        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
665        enum TestEnum2 {
666            A(u8),
667            B([u8; 3]),
668            C(Vec<u8>),
669        }
670
671        validate_enum(TestEnum2::A(2));
672        validate_enum(TestEnum2::B([1, 2, 3]));
673        validate_enum(TestEnum2::C(vec![1, 2, 3]));
674
675        #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
676        #[canonical(prefix = 2u64)]
677        struct Prefixed2(u16);
678        validate(Prefixed2(u16::MAX));
679
680        assert_eq!(
681            &Prefixed1 {
682                a: [1, 2, 3],
683                b: vec![4, 5]
684            }
685            .to_bytes()[..8],
686            &[0u8, 0, 0, 0, 0, 0, 0, 1]
687        );
688        assert_eq!(
689            Prefixed2(u16::MAX).to_bytes(),
690            [0u8, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0xff, 0xff]
691        );
692    }
693}