How do I work with this __IncompleteArrayField<u8> type? Should I even work with it directly, or am I supposed to create my own Struct and then raw pointer/type cast it? The C struct/buffer is pretty straightfoward, but I guess there's a good reason uint8_t data[] can't simply be mapped to something like a Vec<u8>.
For example, I have a function that takes a raw pointer of this buffer type and I need to allocate and assign it some u8s:
extern "C" some_func(output_buffer: *mut *mut some_buffer, ...) {
// set some_buffer to 1, 2, 3, 4
let values = vec![1u8, 2, 3, 4];
...
}
That shows allocating but, maybe I'm missing something obvious here, it's still missing how to write the data. Rewriting that code snippet to look somewhat like my example above:
extern "C" fn some_func(output_buffer: *mut *mut some_buffer) {
let count = 4;
let layout = alloc::from_size_align(
mem::size_of::<usize>() + count * mem::size_of::<u8>(),
cmp::max(mem::align_of::<usize>(), mem::align_of::<u8>())
).unwrap();
let value = alloc(layout) as *mut some_buffer;
// write length and data
// How?
}
Edit: __IncompleteArrayField<T> has as_mut_slice, I can probably use that one to get a raw mut u8 pointer and write data that way.
This is what I came up with. It compiles, and hopefully works :
extern "C" fn some_func(output_buffer: *mut *mut some_buffer) {
let values_to_write = vec![1u8, 2, 3, 4];
unsafe {
let layout = Layout::from_size_align(
mem::size_of::<usize>() + values_to_write.len() * mem::size_of::<u8>(),
cmp::max(mem::align_of::<usize>(), mem::align_of::<u8>())
).unwrap();
let buffer = alloc(layout) as *mut some_buffer;
// Write len
(*buffer).len = values_to_write.len().try_into().unwrap();
// Write data
let data_slice = (*buffer).data.as_mut_slice(values_to_write.len());
for i in 0..values_to_write.len() {
data_slice[i] = values_to_write[i];
}
*output_buffer = buffer;
}
}
Is there an alternative to as_mut_slice() which gives you a raw pointer to the first element? If as_mut_slice() returns a &mut [u8] then you will be violating the requirement that references must refer to initialized data. Instead I'd prefer to do pointer arithmetic with buffer.data.as_mut_ptr().add(i).write(values_to_write[i]).
You can also clean up the Layout calculation by doing something like:
let length_field = Layout::new::<usize>();
let data_field = Layout::array::<u8>(values_to_write.len());
let overall_layout = length_field.extend(data_field);
That way you aren't manually calculating alignment and sizes.