Reputation: 3557
I'm looking through some old (~2014) Rust code and I'm seeing this code block:
fn compile(self, func:&UncompiledFunction<'a>) -> &'a Val {
unsafe {
use std::raw::Repr;
use std::mem::transmute as cast;
let slice = self.repr();
let ty = <&'a str as Compile<'a>>::get_type();
let structure = Val::new(func, &ty);
let offset_data = cast::<_, usize>(&slice.data) - cast::<_, usize>(&slice);
let offset_len = cast::<_, usize>(&slice.len) - cast::<_, usize>(&slice);
func.insn_store_relative(structure, offset_data, func.insn_of(mem::transmute::<_, isize>(slice.data)));
func.insn_store_relative(structure, offset_len, func.insn_of(slice.len));
structure
}
}
According to the docs and this GitHub discussion std::raw::Repr
and std::raw::Slice
have been deprecated in favor of std::slice
functions.
As someone with only a beginner's understanding of the std library I'm unsure how to translate these particular lines from the above block:
let slice = self.repr(); // `self` here is a `static str`
let offset_data = cast::<_, usize>(&slice.data) - cast::<_, usize>(&slice);
let offset_len = cast::<_, usize>(&slice.len) - cast::<_, usize>(&slice);
I was looking through the documentation for Repr
with the hopes that I could produce an analogy with some function in the std::slice
family, but nothing is immediately clear to me.
I'm hoping someone can explain to me what exactly Repr
does (in different language) and what a more updated approach might be.
Upvotes: 3
Views: 649
Reputation: 10180
For x
of type &[T]
or &str
:
x.repr().data
is x.as_ptr()
.x.repr().len
is x.len()
.std::raw::Slice
back to &[T]
or &str
is std::slice::from_raw_parts
(and optionally std::str::from_utf8_unchecked
).However what this code does not just access the pointer and the length, it’s taking the address of those fields in order to compute their offset, presumably to later do some unsafe/unchecked memory reads or writes.
The unhelpful answer is don’t do this. std::raw::Slice
was removed precisely because we didn’t want to stabilize the exact memory layout of &[T]
and &str
. If this is possible at all, consider refactoring the code to not do these unchecked memory accesses but instead e.g. replace the whole string with std::str::from_utf8_unchecked(std::slice::from_raw_parts(new_pointer, new_len))
.
The practical answer is that the memory layout is very unlikely to change, and you’ll probably be ok if you hard-code:
let offset_data = 0;
let offset_len = std::mem::size_of::<usize>();
Upvotes: 3