My application memory-maps a large block of binary data into memory. That binary data consists of fixed structures with 20 bytes each. I have a function that performs all the unsafe reinterpreting:
fn reinterpret_hashblock<'a>(s: &'a [u8]) -> &'a [[u8; 20]] {
const ELEM_SIZE: usize = 20;
assert_eq!(ELEM_SIZE, mem::size_of::<[u8; 20]>());
let elem_count = s.len() / ELEM_SIZE;
if s.len() % ELEM_SIZE != 0 {
panic!("input is not a multiple of the hash size");
}
unsafe { slice::from_raw_parts(s.as_ptr() as *const _, elem_count) }
}
If I just call reinterpret_hashblock()
on the Mmap
Rust borrows from the Mmap and everything is fine. But I cannot encapsulate this in a struct as I cannot return a reference to hash_block
because it borrows from hash_block
which is "owned" by the local function:
struct HashSet<'a> {
mmap: Mmap,
sorted_hashes: &'a [[u8; 20]],
}
impl HashSet<'_> {
fn new(file: &File) -> Self {
let hash_block_data: Mmap =
unsafe { Mmap::map(&file).expect("failed to map hash block into memory") };
let hash_block = reinterpret_hashblock(&hash_block_data);
Self {
mmap: hash_block_data,
sorted_hashes: hash_block,
}
}
// other accessor functions working with sorted_hashes
}
Basically what should end up happening is that Rust keeps the Mmap around for as long as the PasswordSet is kept around. Is there any way to solve this nicely?