The documentation for MaybeUninit says:
There is currently no supported way to create a raw pointer or reference to a field of a struct inside
MaybeUninit<Struct>
. That means it is not possible to create a struct by callingMaybeUninit::uninit::<Struct>()
and then writing to its fields.
This is of course true for repr(Rust)
structs because their layout is unknown. But shouldn't it be possible to partially initialize the fields of a repr(C)
struct since the offset and size for each field is known.
Will this code cause undefined behavior?
#[repr(C)]
pub struct FooBar {
pub foo: u32,
pub bar: u32,
}
pub fn initFields() -> FooBar {
let mut foobar = MaybeUninit::<FooBar>::uninit();
let foobar_mut_ptr = foobar.as_mut_ptr() as *mut u32;
unsafe {
foobar_mut_ptr.offset(0).write(0u32);
foobar_mut_ptr.offset(1).write(1u32);
foobar.assume_init()
}
}
Also, is it ok to read from a partially initialized MaybeUninit<Struct>
?
pub fn readField() {
let mut foobar = MaybeUninit::<FooBar>::uninit();
let foobar_mut_ptr = foobar.as_mut_ptr() as *mut u32;
unsafe {
foobar_mut_ptr.offset(0).write(0u32);
println!("foo={}", foobar_mut_ptr.offset(0).read());
}
}