transmute
on a Vec
is always, 100% wrong, causing undefined behavior, because the layout of Vec
is not specified. However, as the page you linked also mentions, you can use raw pointers and Vec::from_raw_parts
to perform this correctly. user4815162342's answer shows how.
(std::mem::transmute
is the only item in the Rust standard library whose documentation consists mostly of suggestions for how not to use it. Take that how you will.)
However, in this case, from_raw_parts
is also unnecessary. The best way to deal with C strings in Rust is with the wrappers in std::ffi
, CStr
and CString
. There may be better ways to work this in to your real code, but here's one way you could use CStr
to borrow a Vec<c_char>
as a &str
:
const BUF_SIZE: usize = 1000;
let mut info_log: Vec<c_char> = vec![0; BUF_SIZE];
let mut len: usize;
unsafe {
gl::GetShaderInfoLog(shader, BUF_SIZE, &mut len, info_log.as_mut_ptr());
}
let log = Cstr::from_bytes_with_nul(info_log[..len + 1])
.expect("Slice must be nul terminated and contain no nul bytes")
.to_str()
.expect("Slice must be valid UTF-8 text");
Notice there is no unsafe
code except to call the FFI function; you could also use with_capacity
+ set_len
(as in wasmup's answer) to skip initializing the Vec
to 1000 zeros, and use from_bytes_with_nul_unchecked
to skip checking the validity of the returned string.