fuels_core/
lib.rs

1pub mod codec;
2pub mod traits;
3pub mod types;
4mod utils;
5
6pub use utils::*;
7
8use crate::types::errors::Result;
9
10#[derive(Debug, Clone, Default, PartialEq)]
11pub struct Configurable {
12    /// The offset (in bytes) within the binary where the data is located.
13    pub offset: u64,
14    /// The data related to the configurable.
15    pub data: Vec<u8>,
16}
17
18#[derive(Debug, Clone, Default, PartialEq)]
19pub struct Configurables {
20    pub offsets_with_data: Vec<Configurable>,
21}
22
23impl Configurables {
24    pub fn new(offsets_with_data: Vec<Configurable>) -> Self {
25        Self { offsets_with_data }
26    }
27
28    pub fn with_shifted_offsets(self, shift: i64) -> Result<Self> {
29        let new_offsets_with_data = self
30            .offsets_with_data
31            .into_iter()
32            .map(|c| {
33                let new_offset = if shift.is_negative() {
34                    c.offset.checked_sub(shift.unsigned_abs())
35                } else {
36                    c.offset.checked_add(shift.unsigned_abs())
37                };
38
39                let new_offset = new_offset.ok_or_else(|| {
40                    crate::error!(
41                        Other,
42                        "Overflow occurred while shifting offset: {} + {shift}",
43                        c.offset
44                    )
45                })?;
46
47                Ok(Configurable {
48                    offset: new_offset,
49                    data: c.data,
50                })
51            })
52            .collect::<Result<Vec<_>>>()?;
53
54        Ok(Self {
55            offsets_with_data: new_offsets_with_data,
56        })
57    }
58
59    pub fn update_constants_in(&self, binary: &mut [u8]) {
60        for c in &self.offsets_with_data {
61            let offset = c.offset as usize;
62            binary[offset..offset + c.data.len()].copy_from_slice(&c.data)
63        }
64    }
65}
66
67impl From<Configurables> for Vec<Configurable> {
68    fn from(config: Configurables) -> Vec<Configurable> {
69        config.offsets_with_data.clone()
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn test_with_shifted_offsets_positive_shift() {
79        let offsets_with_data = vec![Configurable {
80            offset: 10u64,
81            data: vec![1, 2, 3],
82        }];
83        let configurables = Configurables::new(offsets_with_data.clone());
84        let shifted_configurables = configurables.with_shifted_offsets(5).unwrap();
85        let expected_offsets_with_data = vec![Configurable {
86            offset: 15u64,
87            data: vec![1, 2, 3],
88        }];
89        assert_eq!(
90            shifted_configurables.offsets_with_data,
91            expected_offsets_with_data
92        );
93    }
94
95    #[test]
96    fn test_with_shifted_offsets_negative_shift() {
97        let offsets_with_data = vec![Configurable {
98            offset: 10u64,
99            data: vec![4, 5, 6],
100        }];
101        let configurables = Configurables::new(offsets_with_data.clone());
102        let shifted_configurables = configurables.with_shifted_offsets(-5).unwrap();
103        let expected_offsets_with_data = vec![Configurable {
104            offset: 5u64,
105            data: vec![4, 5, 6],
106        }];
107        assert_eq!(
108            shifted_configurables.offsets_with_data,
109            expected_offsets_with_data
110        );
111    }
112
113    #[test]
114    fn test_with_shifted_offsets_zero_shift() {
115        let offsets_with_data = vec![Configurable {
116            offset: 20u64,
117            data: vec![7, 8, 9],
118        }];
119        let configurables = Configurables::new(offsets_with_data.clone());
120        let shifted_configurables = configurables.with_shifted_offsets(0).unwrap();
121        let expected_offsets_with_data = offsets_with_data;
122        assert_eq!(
123            shifted_configurables.offsets_with_data,
124            expected_offsets_with_data
125        );
126    }
127
128    #[test]
129    fn test_with_shifted_offsets_overflow() {
130        let offsets_with_data = vec![Configurable {
131            offset: u64::MAX - 1,
132            data: vec![1, 2, 3],
133        }];
134        let configurables = Configurables::new(offsets_with_data);
135        let result = configurables.with_shifted_offsets(10);
136        assert!(result.is_err());
137        if let Err(e) = result {
138            assert!(
139                e.to_string()
140                    .contains("Overflow occurred while shifting offset")
141            );
142        }
143    }
144
145    #[test]
146    fn test_with_shifted_offsets_underflow() {
147        let offsets_with_data = vec![Configurable {
148            offset: 5u64,
149            data: vec![4, 5, 6],
150        }];
151        let configurables = Configurables::new(offsets_with_data);
152        let result = configurables.with_shifted_offsets(-10);
153        assert!(result.is_err());
154        if let Err(e) = result {
155            assert!(
156                e.to_string()
157                    .contains("Overflow occurred while shifting offset")
158            );
159        }
160    }
161}