fuels_types/unresolved_bytes.rs
1use crate::constants::WORD_SIZE;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub enum Data {
5 // Write the enclosed data immediately.
6 Inline(Vec<u8>),
7 // The enclosed data should be written somewhere else and only a pointer
8 // should be left behind to point to it.
9 Dynamic(Vec<Data>),
10}
11
12// To get the final encoded bytes, we need to know the address at which these
13// bytes are going to be loaded at. Once the address is given to `resolve`
14// normal bytes can be retrieved.
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
16pub struct UnresolvedBytes {
17 data: Vec<Data>,
18}
19
20impl UnresolvedBytes {
21 pub fn new(data: Vec<Data>) -> Self {
22 Self { data }
23 }
24
25 #[allow(clippy::should_implement_trait)]
26 pub fn default() -> Self {
27 Default::default()
28 }
29
30 /// Uses the `start_addr` to resolve any pointers contained within. Once
31 /// they are resolved the raw bytes are returned.
32 ///
33 /// # Arguments
34 ///
35 /// * `start_addr`: The address at which the encoded bytes are to be loaded
36 /// in.
37 pub fn resolve(&self, start_addr: u64) -> Vec<u8> {
38 Self::resolve_data(&self.data, start_addr)
39 }
40
41 fn resolve_data(data: &[Data], start_addr: u64) -> Vec<u8> {
42 // We must find a place for the dynamic data where it will not bother
43 // anyone. Best place for it is immediately after all the inline/normal
44 // data is encoded.
45
46 let start_of_dynamic_data = start_addr + Self::amount_of_inline_bytes(data);
47
48 let mut inline_data: Vec<u8> = vec![];
49 let mut dynamic_data: Vec<u8> = vec![];
50 for chunk in data {
51 match chunk {
52 Data::Inline(bytes) => inline_data.extend(bytes),
53 Data::Dynamic(chunk_of_dynamic_data) => {
54 let ptr_to_next_free_location: u64 =
55 start_of_dynamic_data + dynamic_data.len() as u64;
56
57 // If this is a vector, its `ptr` will now be encoded, the
58 // `cap` and `len` parts should follow as two Data::Inline
59 // chunks.
60 inline_data.extend(ptr_to_next_free_location.to_be_bytes().to_vec());
61
62 // The dynamic data could have had more dynamic data inside
63 // of it -- think of a Vec<Vec<...>>. Hence Data::Dynamic
64 // doesn't contain bytes but rather more `Data`.
65 let resolved_dynamic_data =
66 Self::resolve_data(chunk_of_dynamic_data, ptr_to_next_free_location);
67
68 dynamic_data.extend(resolved_dynamic_data)
69 }
70 }
71 }
72
73 let mut data = inline_data;
74 data.extend(dynamic_data);
75 data
76 }
77
78 fn amount_of_inline_bytes(data: &[Data]) -> u64 {
79 data.iter()
80 .map(|chunk| match chunk {
81 Data::Inline(bytes) => bytes.len(),
82 Data::Dynamic(_) => {
83 // Only the ptr is encoded inline
84 WORD_SIZE
85 }
86 } as u64)
87 .sum()
88 }
89}