fuel_core_storage/codec/
primitive.rs

1//! The module contains the implementation of the `Postcard` codec.
2//! The codec is used for types that can be represented by an array.
3//! It includes all primitive types and types that are arrays inside
4//! or could be represented by arrays.
5
6use crate::codec::{
7    Decode,
8    Encode,
9};
10use fuel_core_types::{
11    blockchain::primitives::DaBlockHeight,
12    fuel_tx::{
13        TxId,
14        UtxoId,
15    },
16    fuel_types::BlockHeight,
17};
18
19/// The codec is used for types that can be represented by an array.
20/// The `SIZE` const specifies the size of the array used to represent the type.
21pub struct Primitive<const SIZE: usize>;
22
23macro_rules! impl_encode {
24    ($($ty:ty, $size:expr_2021),*) => {
25        $(
26            impl Encode<$ty> for Primitive<{ $size }> {
27                type Encoder<'a> = [u8; { $size }];
28
29                fn encode(t: &$ty) -> Self::Encoder<'_> {
30                    t.to_be_bytes()
31                }
32            }
33        )*
34    };
35}
36macro_rules! impl_decode {
37    ($($ty:ty, $size:expr_2021),*) => {
38        $(
39            impl Decode<$ty> for Primitive<{ $size }> {
40                fn decode(bytes: &[u8]) -> anyhow::Result<$ty> {
41                    Ok(<$ty>::from_be_bytes(<[u8; { $size }]>::try_from(bytes)?))
42                }
43            }
44        )*
45    };
46}
47
48impl_encode! {
49    u8, 1,
50    u16, 2,
51    u32, 4,
52    BlockHeight, 4,
53    DaBlockHeight, 8,
54    u64, 8,
55    u128, 16
56}
57
58impl_decode! {
59    u8, 1,
60    u16, 2,
61    u32, 4,
62    u64, 8,
63    u128, 16
64}
65
66impl Decode<BlockHeight> for Primitive<4> {
67    fn decode(bytes: &[u8]) -> anyhow::Result<BlockHeight> {
68        Ok(BlockHeight::from(<[u8; 4]>::try_from(bytes)?))
69    }
70}
71
72impl Decode<DaBlockHeight> for Primitive<8> {
73    fn decode(bytes: &[u8]) -> anyhow::Result<DaBlockHeight> {
74        Ok(DaBlockHeight::from(<[u8; 8]>::try_from(bytes)?))
75    }
76}
77
78/// Converts the `UtxoId` into an array of bytes.
79pub fn utxo_id_to_bytes(utxo_id: &UtxoId) -> [u8; TxId::LEN + 2] {
80    let mut default = [0; TxId::LEN + 2];
81    default[0..TxId::LEN].copy_from_slice(utxo_id.tx_id().as_ref());
82    default[TxId::LEN..].copy_from_slice(utxo_id.output_index().to_be_bytes().as_slice());
83    default
84}
85
86impl Encode<UtxoId> for Primitive<{ TxId::LEN + 2 }> {
87    type Encoder<'a> = [u8; TxId::LEN + 2];
88
89    fn encode(t: &UtxoId) -> Self::Encoder<'_> {
90        utxo_id_to_bytes(t)
91    }
92}
93
94impl Decode<UtxoId> for Primitive<{ TxId::LEN + 2 }> {
95    fn decode(bytes: &[u8]) -> anyhow::Result<UtxoId> {
96        let bytes = <[u8; TxId::LEN + 2]>::try_from(bytes)?;
97        let tx_id: [u8; TxId::LEN] = bytes[0..TxId::LEN].try_into()?;
98        let output_index = u16::from_be_bytes(bytes[TxId::LEN..].try_into()?);
99        Ok(UtxoId::new(TxId::from(tx_id), output_index))
100    }
101}