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 { 0 } else { ALIGN - modulo }
190}
191
192/// Size after alignment. Saturates on overflow.
193pub const fn aligned_size(len: usize) -> usize {
194    len.saturating_add(alignment_bytes(len))
195}
196
197macro_rules! impl_for_primitives {
198    ($t:ident, $unpadded:literal) => {
199        impl Serialize for $t {
200            const UNALIGNED_BYTES: bool = $unpadded;
201
202            #[inline(always)]
203            fn size_static(&self) -> usize {
204                aligned_size(::core::mem::size_of::<$t>())
205            }
206
207            #[inline(always)]
208            fn size_dynamic(&self) -> usize {
209                0
210            }
211
212            #[inline(always)]
213            fn encode_static<O: Output + ?Sized>(
214                &self,
215                buffer: &mut O,
216            ) -> Result<(), Error> {
217                // Primitive types are zero-padded on left side to a 8-byte boundary.
218                // The resulting value is always well-aligned.
219                let bytes = <$t>::to_be_bytes(*self);
220                for _ in 0..alignment_bytes(bytes.len()) {
221                    // Zero-pad
222                    buffer.push_byte(0)?;
223                }
224                buffer.write(bytes.as_ref())?;
225                Ok(())
226            }
227        }
228
229        impl Deserialize for $t {
230            const UNALIGNED_BYTES: bool = $unpadded;
231
232            fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
233                let mut asset = [0u8; ::core::mem::size_of::<$t>()];
234                buffer.skip(alignment_bytes(asset.len()))?; // Skip zero-padding
235                buffer.read(asset.as_mut())?;
236                Ok(<$t>::from_be_bytes(asset))
237            }
238        }
239    };
240}
241
242impl_for_primitives!(u8, true);
243impl_for_primitives!(u16, false);
244impl_for_primitives!(u32, false);
245impl_for_primitives!(usize, false);
246impl_for_primitives!(u64, false);
247impl_for_primitives!(u128, false);
248
249// Empty tuple `()`, i.e. the unit type takes up no space.
250impl Serialize for () {
251    fn size_static(&self) -> usize {
252        0
253    }
254
255    #[inline(always)]
256    fn size_dynamic(&self) -> usize {
257        0
258    }
259
260    #[inline(always)]
261    fn encode_static<O: Output + ?Sized>(&self, _buffer: &mut O) -> Result<(), Error> {
262        Ok(())
263    }
264}
265
266impl Deserialize for () {
267    fn decode_static<I: Input + ?Sized>(_buffer: &mut I) -> Result<Self, Error> {
268        Ok(())
269    }
270}
271
272/// To protect against malicious large inputs, vector size is limited when decoding.
273pub const VEC_DECODE_LIMIT: usize = 100 * (1 << 20); // 100 MiB
274
275#[cfg(feature = "alloc")]
276impl<T: Serialize> Serialize for Vec<T> {
277    fn size_static(&self) -> usize {
278        8
279    }
280
281    #[inline(always)]
282    fn size_dynamic(&self) -> usize {
283        if T::UNALIGNED_BYTES {
284            aligned_size(self.len())
285        } else {
286            aligned_size(
287                self.iter()
288                    .map(|e| e.size())
289                    .reduce(usize::saturating_add)
290                    .unwrap_or_default(),
291            )
292        }
293    }
294
295    #[inline(always)]
296    // Encode only the size of the vector. Elements will be encoded in the
297    // `encode_dynamic` method.
298    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
299        if self.len() > VEC_DECODE_LIMIT {
300            return Err(Error::AllocationLimit)
301        }
302        let len: u64 = self.len().try_into().expect("msg.len() > u64::MAX");
303        len.encode(buffer)
304    }
305
306    fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
307        // Bytes - Vec<u8> it a separate case without padding for each element.
308        // It should padded at the end if is not % ALIGN
309        if T::UNALIGNED_BYTES {
310            // SAFETY: `UNALIGNED_BYTES` only set for `u8`.
311            let bytes = unsafe { ::core::mem::transmute::<&Vec<T>, &Vec<u8>>(self) };
312            buffer.write(bytes.as_slice())?;
313            for _ in 0..alignment_bytes(self.len()) {
314                buffer.push_byte(0)?;
315            }
316        } else {
317            for e in self.iter() {
318                e.encode(buffer)?;
319            }
320        }
321        Ok(())
322    }
323}
324
325#[cfg(feature = "alloc")]
326impl<T: Deserialize> Deserialize for Vec<T> {
327    // Decode only the capacity of the vector. Elements will be decoded in the
328    // `decode_dynamic` method. The capacity is needed for iteration there.
329    fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
330        let cap = u64::decode(buffer)?;
331        let cap: usize = cap.try_into().map_err(|_| Error::AllocationLimit)?;
332        if cap > VEC_DECODE_LIMIT {
333            return Err(Error::AllocationLimit)
334        }
335        Ok(Vec::with_capacity(cap))
336    }
337
338    fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
339        for _ in 0..self.capacity() {
340            // Bytes - Vec<u8> it a separate case without unpadding for each element.
341            // It should unpadded at the end if is not % ALIGN
342            if T::UNALIGNED_BYTES {
343                let byte = buffer.read_byte()?;
344                // SAFETY: `UNALIGNED_BYTES` implemented set for `u8`.
345                let _self =
346                    unsafe { ::core::mem::transmute::<&mut Vec<T>, &mut Vec<u8>>(self) };
347                _self.push(byte);
348            } else {
349                self.push(T::decode(buffer)?);
350            }
351        }
352
353        if T::UNALIGNED_BYTES {
354            buffer.skip(alignment_bytes(self.capacity()))?;
355        }
356
357        Ok(())
358    }
359}
360
361impl<const N: usize, T: Serialize> Serialize for [T; N] {
362    fn size_static(&self) -> usize {
363        if T::UNALIGNED_BYTES {
364            aligned_size(N)
365        } else {
366            aligned_size(
367                self.iter()
368                    .map(|e| e.size_static())
369                    .reduce(usize::saturating_add)
370                    .unwrap_or_default(),
371            )
372        }
373    }
374
375    #[inline(always)]
376    fn size_dynamic(&self) -> usize {
377        if T::UNALIGNED_BYTES {
378            0
379        } else {
380            aligned_size(
381                self.iter()
382                    .map(|e| e.size_dynamic())
383                    .reduce(usize::saturating_add)
384                    .unwrap_or_default(),
385            )
386        }
387    }
388
389    #[inline(always)]
390    fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
391        // Bytes - [u8; N] it a separate case without padding for each element.
392        // It should padded at the end if is not % ALIGN
393        if T::UNALIGNED_BYTES {
394            // SAFETY: `Type::U8` implemented only for `u8`.
395            let bytes = unsafe { ::core::mem::transmute::<&[T; N], &[u8; N]>(self) };
396            buffer.write(bytes.as_slice())?;
397            for _ in 0..alignment_bytes(N) {
398                buffer.push_byte(0)?;
399            }
400        } else {
401            for e in self.iter() {
402                e.encode_static(buffer)?;
403            }
404        }
405        Ok(())
406    }
407
408    fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
409        for e in self.iter() {
410            e.encode_dynamic(buffer)?;
411        }
412
413        Ok(())
414    }
415}
416
417impl<const N: usize, T: Deserialize> Deserialize for [T; N] {
418    fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
419        if T::UNALIGNED_BYTES {
420            let mut bytes: [u8; N] = [0; N];
421            buffer.read(bytes.as_mut())?;
422            buffer.skip(alignment_bytes(N))?;
423            let ref_typed: &[T; N] = unsafe { core::mem::transmute(&bytes) };
424            let typed: [T; N] = unsafe { core::ptr::read(ref_typed) };
425            Ok(typed)
426        } else {
427            // Spec doesn't say how to deserialize arrays with unaligned
428            // primitives(as `u16`, `u32`, `usize`), so unpad them.
429            // SAFETY: `uninit`` is an array of `MaybUninit`, which do not require
430            // initialization
431            let mut uninit: [MaybeUninit<T>; N] =
432                unsafe { MaybeUninit::uninit().assume_init() };
433            // The following line coerces the pointer to the array to a pointer
434            // to the first array element which is equivalent.
435            for i in 0..N {
436                match T::decode_static(buffer) {
437                    Err(e) => {
438                        for item in uninit.iter_mut().take(i) {
439                            // SAFETY: all elements up to index i (excluded have been
440                            // initialised)
441                            unsafe {
442                                item.assume_init_drop();
443                            }
444                        }
445                        return Err(e)
446                    }
447                    Ok(decoded) => {
448                        // SAFETY: `uninit[i]` is a MaybeUninit which can be
449                        // safely overwritten.
450                        uninit[i].write(decoded);
451
452                        // SAFETY: Point to the next element after every iteration.
453                        // 		 We do this N times therefore this is safe.
454                    }
455                }
456            }
457
458            // SAFETY: All array elements have been initialized above.
459            let init = uninit.map(|v| unsafe { v.assume_init() });
460            Ok(init)
461        }
462    }
463
464    fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
465        for e in self.iter_mut() {
466            e.decode_dynamic(buffer)?;
467        }
468        Ok(())
469    }
470}
471
472#[cfg(feature = "alloc")]
473impl Output for Vec<u8> {
474    fn write(&mut self, bytes: &[u8]) -> Result<(), Error> {
475        self.extend_from_slice(bytes);
476        Ok(())
477    }
478}
479
480impl Output for &'_ mut [u8] {
481    fn write(&mut self, from: &[u8]) -> Result<(), Error> {
482        if from.len() > self.len() {
483            return Err(Error::BufferIsTooShort)
484        }
485        let len = from.len();
486        self[..len].copy_from_slice(from);
487        // We need to reduce the inner slice by `len`, because we already filled them.
488        let reduced = &mut self[len..];
489
490        // Compiler is not clever enough to allow it.
491        // https://stackoverflow.com/questions/25730586/how-can-i-create-my-own-data-structure-with-an-iterator-that-returns-mutable-ref
492        *self = unsafe { &mut *(reduced as *mut [u8]) };
493        Ok(())
494    }
495}
496
497impl Input for &'_ [u8] {
498    fn remaining(&mut self) -> usize {
499        self.len()
500    }
501
502    fn peek(&self, into: &mut [u8]) -> Result<(), Error> {
503        if into.len() > self.len() {
504            return Err(Error::BufferIsTooShort)
505        }
506
507        let len = into.len();
508        into.copy_from_slice(&self[..len]);
509        Ok(())
510    }
511
512    fn read(&mut self, into: &mut [u8]) -> Result<(), Error> {
513        if into.len() > self.len() {
514            return Err(Error::BufferIsTooShort)
515        }
516
517        let len = into.len();
518        into.copy_from_slice(&self[..len]);
519        *self = &self[len..];
520        Ok(())
521    }
522
523    fn skip(&mut self, n: usize) -> Result<(), Error> {
524        if n > self.len() {
525            return Err(Error::BufferIsTooShort)
526        }
527
528        *self = &self[n..];
529        Ok(())
530    }
531}
532
533#[cfg(test)]
534mod tests {
535    use super::*;
536
537    fn validate<T: Serialize + Deserialize + Eq + core::fmt::Debug>(t: T) {
538        let bytes = t.to_bytes();
539        let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
540        assert_eq!(t, t2);
541        assert_eq!(t.to_bytes(), t2.to_bytes());
542
543        let mut vec = Vec::new();
544        t.encode_static(&mut vec).expect("Encode failed");
545        assert_eq!(vec.len(), t.size_static());
546    }
547
548    fn validate_enum<T: Serialize + Deserialize + Eq + fmt::Debug>(t: T) {
549        let bytes = t.to_bytes();
550        let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
551        assert_eq!(t, t2);
552        assert_eq!(t.to_bytes(), t2.to_bytes());
553
554        let mut vec = Vec::new();
555        t.encode_static(&mut vec).expect("Encode failed");
556        assert_eq!(vec.len(), t.size_static());
557        t.encode_dynamic(&mut vec).expect("Encode failed");
558        assert_eq!(vec.len(), t.size());
559
560        let mut vec2 = Vec::new();
561        t.encode_dynamic(&mut vec2).expect("Encode failed");
562        assert_eq!(vec2.len(), t.size_dynamic());
563    }
564
565    #[test]
566    fn test_canonical_encode_decode() {
567        validate(());
568        validate(123u8);
569        validate(u8::MAX);
570        validate(123u16);
571        validate(u16::MAX);
572        validate(123u32);
573        validate(u32::MAX);
574        validate(123u64);
575        validate(u64::MAX);
576        validate(123u128);
577        validate(u128::MAX);
578        validate(Vec::<u8>::new());
579        validate(Vec::<u16>::new());
580        validate(Vec::<u32>::new());
581        validate(Vec::<u64>::new());
582        validate(Vec::<u128>::new());
583        validate(vec![1u8]);
584        validate(vec![1u16]);
585        validate(vec![1u32]);
586        validate(vec![1u64]);
587        validate(vec![1u128]);
588        validate(vec![1u8, 2u8]);
589        validate(vec![1u16, 2u16]);
590        validate(vec![1u32, 2u32]);
591        validate(vec![1u64, 2u64]);
592        validate(vec![1u128, 2u128]);
593
594        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
595        struct TestStruct1 {
596            a: u8,
597            b: u16,
598        }
599
600        let t = TestStruct1 { a: 123, b: 456 };
601        assert_eq!(t.size_static(), 16);
602        assert_eq!(t.size(), 16);
603        validate(t);
604
605        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
606        struct TestStruct2 {
607            a: u8,
608            v: Vec<u8>,
609            b: u16,
610            arr0: [u8; 0],
611            arr1: [u8; 2],
612            arr2: [u16; 3],
613            arr3: [u64; 4],
614        }
615
616        validate(TestStruct2 {
617            a: 123,
618            v: vec![1, 2, 3],
619            b: 456,
620            arr0: [],
621            arr1: [1, 2],
622            arr2: [1, 2, u16::MAX],
623            arr3: [0, 3, 1111, u64::MAX],
624        });
625
626        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
627        #[repr(transparent)]
628        struct TestStruct3([u8; 64]);
629
630        let t = TestStruct3([1; 64]);
631        assert_eq!(t.size_static(), 64);
632        assert_eq!(t.size(), 64);
633        validate(t);
634
635        #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
636        #[canonical(prefix = 1u64)]
637        struct Prefixed1 {
638            a: [u8; 3],
639            b: Vec<u8>,
640        }
641        validate(Prefixed1 {
642            a: [1, 2, 3],
643            b: vec![4, 5, 6],
644        });
645
646        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
647        #[repr(u8)]
648        enum TestEnum1 {
649            A,
650            B,
651            C = 0x13,
652            D,
653        }
654
655        validate(TestEnum1::A);
656        validate(TestEnum1::B);
657        validate(TestEnum1::C);
658        validate(TestEnum1::D);
659
660        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
661        enum TestEnum2 {
662            A(u8),
663            B([u8; 3]),
664            C(Vec<u8>),
665        }
666
667        validate_enum(TestEnum2::A(2));
668        validate_enum(TestEnum2::B([1, 2, 3]));
669        validate_enum(TestEnum2::C(vec![1, 2, 3]));
670
671        #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
672        #[canonical(prefix = 2u64)]
673        struct Prefixed2(u16);
674        validate(Prefixed2(u16::MAX));
675
676        assert_eq!(
677            &Prefixed1 {
678                a: [1, 2, 3],
679                b: vec![4, 5]
680            }
681            .to_bytes()[..8],
682            &[0u8, 0, 0, 0, 0, 0, 0, 1]
683        );
684        assert_eq!(
685            Prefixed2(u16::MAX).to_bytes(),
686            [0u8, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0xff, 0xff]
687        );
688    }
689}