@@ -127,6 +127,43 @@ impl Memory {
127127 . and_then ( |segment| segment. get ( offset) )
128128 . and_then ( |mem_cell| mem_cell. value ( ) )
129129 }
130+
131+ /// Retrieves a fixed-size array of field elements starting from a given address.
132+ ///
133+ /// This function reads `DIM` consecutive memory cells starting from `start_address`,
134+ /// expecting each cell to contain an integer (`MemoryValue::Int`). It's a generic
135+ /// way to perform the "vectorized memory access". We need to check further if it is better
136+ /// to use vectorized memory cells directly.
137+ ///
138+ /// # Arguments
139+ /// * `start_address`: The `MemoryAddress` of the first element of the vector.
140+ pub ( crate ) fn get_array < F , const DIM : usize > (
141+ & self ,
142+ start_address : MemoryAddress ,
143+ ) -> Result < [ MemoryValue < F > ; DIM ] , MemoryError < F > >
144+ where
145+ F : PrimeField64 ,
146+ {
147+ // Initialize an array to store the result.
148+ let mut result = [ MemoryValue :: default ( ) ; DIM ] ;
149+
150+ // Iterate from 0 to DIM-1 to read each element of the vector.
151+ for ( i, res) in result. iter_mut ( ) . enumerate ( ) . take ( DIM ) {
152+ // Calculate the address of the current element by adding the index `i` to the start offset.
153+ let current_addr = start_address. add_usize ( i) . map_err ( MemoryError :: Math ) ?;
154+
155+ // Retrieve the value from the calculated address.
156+ let mem_val = self
157+ . get ( current_addr)
158+ . ok_or ( MemoryError :: UninitializedMemory ( current_addr) ) ?;
159+
160+ // Assign the validated field element to the result array.
161+ * res = mem_val;
162+ }
163+
164+ // Return the completed array.
165+ Ok ( result)
166+ }
130167}
131168
132169#[ cfg( test) ]
@@ -156,7 +193,7 @@ mod tests {
156193 } ;
157194 let val = MemoryValue :: < F > :: Int ( F :: from_u64 ( 100 ) ) ;
158195
159- assert ! ( memory. insert( addr, val. clone ( ) ) . is_ok( ) ) ;
196+ assert ! ( memory. insert( addr, val) . is_ok( ) ) ;
160197 assert_eq ! ( memory. get( addr) , Some ( val) ) ;
161198 }
162199
@@ -169,7 +206,7 @@ mod tests {
169206 } ;
170207 let val = MemoryValue :: < F > :: Int ( F :: from_u64 ( 200 ) ) ;
171208
172- assert ! ( memory. insert( addr, val. clone ( ) ) . is_ok( ) ) ;
209+ assert ! ( memory. insert( addr, val) . is_ok( ) ) ;
173210
174211 // Verify the segment was resized and padded with NONE.
175212 assert_eq ! ( memory. data[ 0 ] . len( ) , 6 ) ;
@@ -197,9 +234,9 @@ mod tests {
197234 let val = MemoryValue :: < F > :: Int ( F :: from_u64 ( 300 ) ) ;
198235
199236 // First insert should succeed.
200- assert ! ( memory. insert( addr, val. clone ( ) ) . is_ok( ) ) ;
237+ assert ! ( memory. insert( addr, val) . is_ok( ) ) ;
201238 // Inserting the exact same value again should also succeed.
202- assert ! ( memory. insert( addr, val. clone ( ) ) . is_ok( ) ) ;
239+ assert ! ( memory. insert( addr, val) . is_ok( ) ) ;
203240
204241 assert_eq ! ( memory. get( addr) , Some ( val) ) ;
205242 }
@@ -228,10 +265,10 @@ mod tests {
228265 let val2 = MemoryValue :: < F > :: Int ( F :: from_u64 ( 600 ) ) ;
229266
230267 // First write is OK.
231- memory. insert ( addr, val1. clone ( ) ) . unwrap ( ) ;
268+ memory. insert ( addr, val1) . unwrap ( ) ;
232269
233270 // Second write with a different value should fail.
234- let err = memory. insert ( addr, val2. clone ( ) ) . unwrap_err ( ) ;
271+ let err = memory. insert ( addr, val2) . unwrap_err ( ) ;
235272 assert_eq ! (
236273 err,
237274 MemoryError :: InconsistentMemory ( Box :: new( ( addr, val1, val2) ) )
@@ -251,7 +288,7 @@ mod tests {
251288 } ;
252289 let val = MemoryValue :: < F > :: Address ( address_value) ;
253290
254- assert ! ( memory. insert( addr_to_insert_at, val. clone ( ) ) . is_ok( ) ) ;
291+ assert ! ( memory. insert( addr_to_insert_at, val) . is_ok( ) ) ;
255292 assert_eq ! ( memory. get( addr_to_insert_at) , Some ( val) ) ;
256293 }
257294
@@ -263,7 +300,7 @@ mod tests {
263300 offset : 0 ,
264301 } ;
265302 let val = MemoryValue :: < F > :: Int ( F :: from_u64 ( 123 ) ) ;
266- memory. insert ( addr, val. clone ( ) ) . unwrap ( ) ;
303+ memory. insert ( addr, val) . unwrap ( ) ;
267304
268305 assert_eq ! ( memory. get( addr) , Some ( val) ) ;
269306 }
@@ -310,4 +347,62 @@ mod tests {
310347 } ;
311348 assert_eq ! ( memory. get:: <F >( gap_addr) , None ) ;
312349 }
350+
351+ #[ test]
352+ fn test_get_array_successful ( ) {
353+ // Setup: Create a memory instance with one segment.
354+ let mut memory = create_memory_with_segments ( 1 ) ;
355+ // Define the starting address for the array read.
356+ let start_addr = MemoryAddress {
357+ segment_index : 0 ,
358+ offset : 2 ,
359+ } ;
360+ // Define the array of mixed `MemoryValue` types to insert.
361+ let values_to_insert = [
362+ MemoryValue :: Int ( F :: from_u64 ( 100 ) ) ,
363+ MemoryValue :: Address ( MemoryAddress :: new ( 0 , 99 ) ) ,
364+ MemoryValue :: Int ( F :: from_u64 ( 300 ) ) ,
365+ ] ;
366+
367+ // Loop through the data and insert each value at a consecutive address.
368+ for ( i, & val) in values_to_insert. iter ( ) . enumerate ( ) {
369+ memory
370+ // Calculate the address for the current item: `start_addr + i`.
371+ . insert ( start_addr. add_usize :: < F > ( i) . unwrap ( ) , val)
372+ . unwrap ( ) ;
373+ }
374+
375+ // Execute: Call `get_array` to retrieve the data.
376+ let result: Result < [ MemoryValue < F > ; 3 ] , _ > = memory. get_array ( start_addr) ;
377+ // Verify: The retrieved array should be identical to the one we inserted.
378+ assert_eq ! ( result. unwrap( ) , values_to_insert) ;
379+ }
380+
381+ #[ test]
382+ fn test_get_array_fails_on_uninitialized ( ) {
383+ // Setup: Create a memory instance with one segment.
384+ let mut memory = create_memory_with_segments ( 1 ) ;
385+ // Define the starting address.
386+ let start_addr = MemoryAddress {
387+ segment_index : 0 ,
388+ offset : 0 ,
389+ } ;
390+ // Insert only the *first* value of the array we intend to read.
391+ memory
392+ . insert ( start_addr, MemoryValue :: Int ( F :: from_u64 ( 100 ) ) )
393+ . unwrap ( ) ;
394+
395+ // Execute: Attempt to read a 2-element array. This should fail on the second element.
396+ let result: Result < [ MemoryValue < F > ; 2 ] , _ > = memory. get_array ( start_addr) ;
397+ // Verify: The operation should fail.
398+ assert ! ( result. is_err( ) ) ;
399+ // Verify: The error must be `UninitializedMemory` at the exact address of the missing element.
400+ assert_eq ! (
401+ result. unwrap_err( ) ,
402+ MemoryError :: UninitializedMemory ( MemoryAddress {
403+ segment_index: 0 ,
404+ offset: 1
405+ } )
406+ ) ;
407+ }
313408}
0 commit comments