I am struggling to cast a nested array, say of type [5][5]u8, to the corresponding nested slice type like [][]u8.
I have a function which accepts a nested slice:
fn func(arg: [][]u8) void {...}
I have a variable of nested arrays:
var a = [_][5]u8{[_]u8{1} ** 5} ** 5;
I want to pass a to func. I tried the following approaches but they do not work:
func(a[0..])
func(a[0..][0..])
How can I properly cast to nested slice from nested array?
>Solution :
Such a cast is not possible.
You would have to allocate memory for the outer slice in some way. For example, using the stack:
const std = @import("std");
pub fn main() !void {
var arr = [_][5]u8{[_]u8{1} ** 5} ** 5;
var outer_slice_memory: [5][]u8 = undefined;
for (&arr, 0..) |*sub, i| {
outer_slice_memory[i] = sub[0..];
}
foo(&outer_slice_memory);
}
fn foo(slices: [][]u8) void {
std.log.info("{any}", .{ slices });
}
This prints:
info: { { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1 } }
Note, the lifetimes: outer_slice_memory becomes invalid after main exists.
Explanation
An array of arrays like [5][5]u8 is just 25 consecutive bytes in memory.
But a slice consists of two fields: a many-item pointer plus length. Something like this: struct { ptr: [*]T, len: usize }. So, a slice of slices would contain a many-item pointer to memory with other slices.
In other words, an array of arrays and a slice of slices have very different memory representations. So a direct cast is not possible.