formualizer_eval/engine/arena/
array.rs1use super::value_ref::ValueRef;
4use std::fmt;
5
6#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
8pub struct ArrayRef(pub u32);
9
10impl ArrayRef {
11 pub fn as_u32(self) -> u32 {
12 self.0
13 }
14}
15
16impl fmt::Display for ArrayRef {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 write!(f, "ArrayRef({})", self.0)
19 }
20}
21
22#[derive(Debug)]
24pub struct ArrayArena {
25 dimensions: Vec<(u32, u32)>,
27 elements: Vec<ValueRef>,
29 offsets: Vec<u32>,
31}
32
33impl ArrayArena {
34 pub fn new() -> Self {
35 Self {
36 dimensions: Vec::new(),
37 elements: Vec::new(),
38 offsets: vec![0], }
40 }
41
42 pub fn with_capacity(array_count: usize) -> Self {
43 Self {
44 dimensions: Vec::with_capacity(array_count),
45 elements: Vec::with_capacity(array_count * 10), offsets: {
47 let mut v = Vec::with_capacity(array_count + 1);
48 v.push(0);
49 v
50 },
51 }
52 }
53
54 pub fn insert(&mut self, rows: u32, cols: u32, elements: Vec<ValueRef>) -> ArrayRef {
56 let expected_len = (rows * cols) as usize;
57 assert_eq!(
58 elements.len(),
59 expected_len,
60 "Array dimensions {}x{} don't match element count {}",
61 rows,
62 cols,
63 elements.len()
64 );
65
66 let index = self.dimensions.len() as u32;
67 if index == u32::MAX {
68 panic!("Array arena overflow: too many arrays");
69 }
70
71 self.dimensions.push((rows, cols));
73
74 self.elements.extend(elements);
76
77 let new_offset = self.elements.len() as u32;
79 self.offsets.push(new_offset);
80
81 ArrayRef(index)
82 }
83
84 pub fn insert_2d(&mut self, array: Vec<Vec<ValueRef>>) -> ArrayRef {
86 if array.is_empty() {
87 return self.insert(0, 0, Vec::new());
88 }
89
90 let rows = array.len() as u32;
91 let cols = array[0].len() as u32;
92
93 for (i, row) in array.iter().enumerate() {
95 assert_eq!(
96 row.len(),
97 cols as usize,
98 "Row {} has {} columns, expected {}",
99 i,
100 row.len(),
101 cols
102 );
103 }
104
105 let elements: Vec<ValueRef> = array.into_iter().flatten().collect();
107 self.insert(rows, cols, elements)
108 }
109
110 #[inline]
112 pub fn dimensions(&self, r: ArrayRef) -> Option<(u32, u32)> {
113 self.dimensions.get(r.0 as usize).copied()
114 }
115
116 #[inline]
118 pub fn elements(&self, r: ArrayRef) -> Option<&[ValueRef]> {
119 let index = r.0 as usize;
120 if index >= self.dimensions.len() {
121 return None;
122 }
123
124 let start = self.offsets[index] as usize;
125 let end = self.offsets[index + 1] as usize;
126 Some(&self.elements[start..end])
127 }
128
129 #[inline]
131 pub fn get_element(&self, r: ArrayRef, row: u32, col: u32) -> Option<ValueRef> {
132 let (rows, cols) = self.dimensions(r)?;
133 if row >= rows || col >= cols {
134 return None;
135 }
136
137 let elements = self.elements(r)?;
138 let index = (row * cols + col) as usize;
139 elements.get(index).copied()
140 }
141
142 pub fn get_2d(&self, r: ArrayRef) -> Option<Vec<Vec<ValueRef>>> {
144 let (rows, cols) = self.dimensions(r)?;
145 let elements = self.elements(r)?;
146
147 if rows == 0 || cols == 0 {
148 return Some(Vec::new());
149 }
150
151 let mut result = Vec::with_capacity(rows as usize);
152 for row in 0..rows {
153 let start = (row * cols) as usize;
154 let end = start + cols as usize;
155 result.push(elements[start..end].to_vec());
156 }
157
158 Some(result)
159 }
160
161 pub fn len(&self) -> usize {
163 self.dimensions.len()
164 }
165
166 pub fn is_empty(&self) -> bool {
168 self.dimensions.is_empty()
169 }
170
171 pub fn total_elements(&self) -> usize {
173 self.elements.len()
174 }
175
176 pub fn memory_usage(&self) -> usize {
178 self.dimensions.capacity() * std::mem::size_of::<(u32, u32)>()
179 + self.elements.capacity() * std::mem::size_of::<ValueRef>()
180 + self.offsets.capacity() * std::mem::size_of::<u32>()
181 }
182
183 pub fn clear(&mut self) {
185 self.dimensions.clear();
186 self.elements.clear();
187 self.offsets.clear();
188 self.offsets.push(0);
189 }
190}
191
192impl Default for ArrayArena {
193 fn default() -> Self {
194 Self::new()
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn test_array_arena_basic() {
204 let mut arena = ArrayArena::new();
205
206 let elements = vec![
208 ValueRef::from_raw(1),
209 ValueRef::from_raw(2),
210 ValueRef::from_raw(3),
211 ValueRef::from_raw(4),
212 ];
213
214 let array_ref = arena.insert(2, 2, elements);
215
216 assert_eq!(arena.dimensions(array_ref), Some((2, 2)));
217 assert_eq!(arena.len(), 1);
218 assert_eq!(arena.total_elements(), 4);
219 }
220
221 #[test]
222 fn test_array_arena_2d_insert() {
223 let mut arena = ArrayArena::new();
224
225 let array = vec![
226 vec![
227 ValueRef::from_raw(1),
228 ValueRef::from_raw(2),
229 ValueRef::from_raw(3),
230 ],
231 vec![
232 ValueRef::from_raw(4),
233 ValueRef::from_raw(5),
234 ValueRef::from_raw(6),
235 ],
236 ];
237
238 let array_ref = arena.insert_2d(array);
239
240 assert_eq!(arena.dimensions(array_ref), Some((2, 3)));
241
242 assert_eq!(
244 arena.get_element(array_ref, 0, 0),
245 Some(ValueRef::from_raw(1))
246 );
247 assert_eq!(
248 arena.get_element(array_ref, 0, 2),
249 Some(ValueRef::from_raw(3))
250 );
251 assert_eq!(
252 arena.get_element(array_ref, 1, 0),
253 Some(ValueRef::from_raw(4))
254 );
255 assert_eq!(
256 arena.get_element(array_ref, 1, 2),
257 Some(ValueRef::from_raw(6))
258 );
259 }
260
261 #[test]
262 fn test_array_arena_get_2d() {
263 let mut arena = ArrayArena::new();
264
265 let original = vec![
266 vec![ValueRef::from_raw(1), ValueRef::from_raw(2)],
267 vec![ValueRef::from_raw(3), ValueRef::from_raw(4)],
268 vec![ValueRef::from_raw(5), ValueRef::from_raw(6)],
269 ];
270
271 let array_ref = arena.insert_2d(original.clone());
272 let retrieved = arena.get_2d(array_ref).unwrap();
273
274 assert_eq!(retrieved, original);
275 }
276
277 #[test]
278 fn test_array_arena_multiple_arrays() {
279 let mut arena = ArrayArena::new();
280
281 let arr1 = vec![vec![ValueRef::from_raw(1), ValueRef::from_raw(2)]];
282 let arr2 = vec![
283 vec![ValueRef::from_raw(3)],
284 vec![ValueRef::from_raw(4)],
285 vec![ValueRef::from_raw(5)],
286 ];
287 let arr3 = vec![
288 vec![
289 ValueRef::from_raw(6),
290 ValueRef::from_raw(7),
291 ValueRef::from_raw(8),
292 ],
293 vec![
294 ValueRef::from_raw(9),
295 ValueRef::from_raw(10),
296 ValueRef::from_raw(11),
297 ],
298 ];
299
300 let ref1 = arena.insert_2d(arr1.clone());
301 let ref2 = arena.insert_2d(arr2.clone());
302 let ref3 = arena.insert_2d(arr3.clone());
303
304 assert_eq!(arena.len(), 3);
305 assert_eq!(arena.total_elements(), 11);
306
307 assert_eq!(arena.get_2d(ref1), Some(arr1));
308 assert_eq!(arena.get_2d(ref2), Some(arr2));
309 assert_eq!(arena.get_2d(ref3), Some(arr3));
310 }
311
312 #[test]
313 fn test_array_arena_empty_array() {
314 let mut arena = ArrayArena::new();
315
316 let array_ref = arena.insert(0, 0, Vec::new());
317
318 assert_eq!(arena.dimensions(array_ref), Some((0, 0)));
319 assert_eq!(arena.elements(array_ref), Some(&[][..]));
320 assert_eq!(arena.get_2d(array_ref), Some(Vec::new()));
321 }
322
323 #[test]
324 fn test_array_arena_single_element() {
325 let mut arena = ArrayArena::new();
326
327 let array_ref = arena.insert(1, 1, vec![ValueRef::from_raw(42)]);
328
329 assert_eq!(arena.dimensions(array_ref), Some((1, 1)));
330 assert_eq!(
331 arena.get_element(array_ref, 0, 0),
332 Some(ValueRef::from_raw(42))
333 );
334 assert_eq!(
335 arena.get_2d(array_ref),
336 Some(vec![vec![ValueRef::from_raw(42)]])
337 );
338 }
339
340 #[test]
341 fn test_array_arena_out_of_bounds() {
342 let mut arena = ArrayArena::new();
343
344 let array_ref = arena.insert(2, 3, vec![ValueRef::from_raw(0); 6]);
345
346 assert_eq!(
347 arena.get_element(array_ref, 0, 0),
348 Some(ValueRef::from_raw(0))
349 );
350 assert_eq!(
351 arena.get_element(array_ref, 1, 2),
352 Some(ValueRef::from_raw(0))
353 );
354 assert_eq!(arena.get_element(array_ref, 2, 0), None); assert_eq!(arena.get_element(array_ref, 0, 3), None); }
357
358 #[test]
359 #[should_panic(expected = "Array dimensions 2x3 don't match element count 5")]
360 fn test_array_arena_dimension_mismatch() {
361 let mut arena = ArrayArena::new();
362 arena.insert(2, 3, vec![ValueRef::from_raw(0); 5]);
363 }
364
365 #[test]
366 #[should_panic(expected = "Row 1 has 2 columns, expected 3")]
367 fn test_array_arena_inconsistent_rows() {
368 let mut arena = ArrayArena::new();
369
370 let array = vec![
371 vec![
372 ValueRef::from_raw(1),
373 ValueRef::from_raw(2),
374 ValueRef::from_raw(3),
375 ],
376 vec![ValueRef::from_raw(4), ValueRef::from_raw(5)], ];
378
379 arena.insert_2d(array);
380 }
381
382 #[test]
383 fn test_array_arena_clear() {
384 let mut arena = ArrayArena::new();
385
386 arena.insert_2d(vec![vec![ValueRef::from_raw(1), ValueRef::from_raw(2)]]);
387 arena.insert_2d(vec![vec![ValueRef::from_raw(3), ValueRef::from_raw(4)]]);
388
389 assert_eq!(arena.len(), 2);
390 assert_eq!(arena.total_elements(), 4);
391
392 arena.clear();
393
394 assert_eq!(arena.len(), 0);
395 assert_eq!(arena.total_elements(), 0);
396 assert!(arena.is_empty());
397 }
398
399 #[test]
400 fn test_array_arena_memory_usage() {
401 let mut arena = ArrayArena::with_capacity(10);
402
403 let initial_memory = arena.memory_usage();
404
405 for i in 0..10 {
406 arena.insert(10, 10, vec![ValueRef::from_raw(i); 100]);
407 }
408
409 let final_memory = arena.memory_usage();
410 assert!(final_memory >= initial_memory);
411 }
412}