module multiarray struct MultiArray[T] { mut: len int cap int tags map[int]string fields map[string]MultiArrayField } struct MultiArrayField { data voidptr } fn MultiArray.new[T](len int, cap int, init T) MultiArray[T] { mut result := MultiArray[T]{len: len, cap: cap} $for field in T.fields { result.fields[field.name + 's'] = MultiArrayField{ data: unsafe { vcalloc(u64(cap) * sizeof(T)) } } } return result } fn (mut ma MultiArray[T]) add[T](table string, item T) { if ma.len >= ma.cap { unsafe { ma.grow() } } $for field in T.fields { if field.name == table { ma.tags[ma.len] = table ma.len++ } field_name := field.name + 's' mut field_data_ptr := unsafe { ma.fields[field_name].data } unsafe { vmemcpy(&u8(field_data_ptr) + sizeof(T) * u64(ma.len), item, sizeof(T)) } } } @[unsafe] fn (mut ma MultiArray[T]) grow() { new_cap := if ma.cap == 0 { 1 } else { ma.cap * 2 } $for field in T.fields { field_name := field.name + 's' old_data := &T(ma.fields[field_name].data) new_data := vcalloc(u64(new_cap) * sizeof(T)) vmemcpy(new_data, old_data, u64(ma.len) * sizeof(T)) ma.fields[field_name] = MultiArrayField{ data: new_data } } ma.cap = new_cap } fn (ma MultiArray[T]) get(index int) ?T { if index < 0 || index >= ma.len { return none } mut result := T{} $for field in T.fields { field_name := field.name + 's' field_data_ptr := unsafe { ma.fields[field_name].data } unsafe { vmemcpy(&result, &u8(field_data_ptr) + sizeof(T) * u64(index), sizeof(T)) } } return result } @[unsafe] fn (mut ma MultiArray[T]) free() { $for field in T.fields { field_name := field.name + 's' if ma.fields[field_name].data != nil { free( ma.fields[field_name].data ) ma.fields[field_name] = MultiArrayField{nil} } } ma.len = 0; ma.cap = 0 } fn (mut ma MultiArray[T]) iter() Iterator[T] { return Iterator[T]{ma,0} } struct Iterator[T] { mut: ma MultiArray[T] i int } struct IteratorEntry[T] { tag string data T } fn (mut it Iterator[T]) next() ?IteratorEntry[T] { defer { it.i++ } if it.i >= it.ma.len { return none } val := it.ma.get(it.i) or { return none } return IteratorEntry[T]{it.ma.tags[it.i],val} }