11use crate :: { ExitError , ExitFatal } ;
22use alloc:: vec:: Vec ;
3- use core:: cmp:: min;
3+ use core:: cmp:: { max , min} ;
44use core:: ops:: { BitAnd , Not } ;
55use primitive_types:: U256 ;
66
@@ -181,6 +181,15 @@ impl Memory {
181181
182182 self . set ( memory_offset, data, Some ( ulen) )
183183 }
184+
185+ /// Copies part of the memory inside another part of itself.
186+ pub fn copy ( & mut self , dst : usize , src : usize , len : usize ) {
187+ let resize_offset = max ( dst, src) ;
188+ if self . data . len ( ) < resize_offset + len {
189+ self . data . resize ( resize_offset + len, 0 ) ;
190+ }
191+ self . data . copy_within ( src..src + len, dst) ;
192+ }
184193}
185194
186195/// Rounds up `x` to the closest multiple of 32. If `x % 32 == 0` then `x` is returned.
@@ -192,7 +201,7 @@ fn next_multiple_of_32(x: U256) -> Option<U256> {
192201
193202#[ cfg( test) ]
194203mod tests {
195- use super :: { next_multiple_of_32, U256 } ;
204+ use super :: { next_multiple_of_32, Memory , U256 } ;
196205
197206 #[ test]
198207 fn test_next_multiple_of_32 ( ) {
@@ -225,4 +234,49 @@ mod tests {
225234 }
226235 }
227236 }
237+
238+ #[ test]
239+ fn test_memory_copy_works ( ) {
240+ // Create a new instance of memory
241+ let mut memory = Memory :: new ( 100usize ) ;
242+
243+ // Set the [0,0,0,1,2,3,4] array as memory data.
244+ //
245+ // We insert the [1,2,3,4] array on index 3,
246+ // that's why we have the zero padding at the beginning.
247+ memory. set ( 3usize , & [ 1u8 , 2u8 , 3u8 , 4u8 ] , None ) . unwrap ( ) ;
248+ assert_eq ! ( memory. data( ) , & [ 0u8 , 0u8 , 0u8 , 1u8 , 2u8 , 3u8 , 4u8 ] . to_vec( ) ) ;
249+
250+ // Copy 1 byte into index 0.
251+ // As the length is 1, we only copy the byte present on index 3.
252+ memory. copy ( 0usize , 3usize , 1usize ) ;
253+
254+ // Now the new memory data results in [1,0,0,1,2,3,4]
255+ assert_eq ! ( memory. data( ) , & [ 1u8 , 0u8 , 0u8 , 1u8 , 2u8 , 3u8 , 4u8 ] . to_vec( ) ) ;
256+ }
257+
258+ #[ test]
259+ fn test_memory_copy_resize ( ) {
260+ // Create a new instance of memory
261+ let mut memory = Memory :: new ( 100usize ) ;
262+
263+ // Set the [0,0,0,1,2,3,4] array as memory data.
264+ //
265+ // We insert the [1,2,3,4] array on index 3,
266+ // that's why we have the zero padding at the beginning.
267+ memory. set ( 3usize , & [ 1u8 , 2u8 , 3u8 , 4u8 ] , None ) . unwrap ( ) ;
268+ assert_eq ! ( memory. data( ) , & [ 0u8 , 0u8 , 0u8 , 1u8 , 2u8 , 3u8 , 4u8 ] . to_vec( ) ) ;
269+
270+ // Copy 2 bytes into index 3.
271+ // As the length is 2, we copy the bytes present on indexes 6 and 7,
272+ // which are [4,0].
273+ memory. copy ( 3usize , 6usize , 2usize ) ;
274+
275+ // Now the new memory data results in [0, 0, 0, 4, 0, 3, 4, 0].
276+ // An extra element is added due to rezising.
277+ assert_eq ! (
278+ memory. data( ) ,
279+ & [ 0u8 , 0u8 , 0u8 , 4u8 , 0u8 , 3u8 , 4u8 , 0u8 ] . to_vec( )
280+ ) ;
281+ }
228282}
0 commit comments