use std::fs;
use std::io;
use std::mem;
use std::os::windows::io::AsRawHandle;
use std::ptr;
extern crate winapi;
#[derive(Debug)]
pub struct PlatformData {
#[allow(dead_code)] file: fs::File,
mapping_handle: winapi::um::winnt::HANDLE,
}
impl Drop for PlatformData {
fn drop (&mut self) {
if self.mapping_handle != ptr::null_mut() {
let success = unsafe { winapi::um::handleapi::CloseHandle(self.mapping_handle) };
assert!(success != 0);
}
}
}
pub fn map_file(file: fs::File) -> io::Result<(*const u8, usize, PlatformData)> {
let file_handle = file.as_raw_handle();
let length = file.metadata()?.len();
if length > usize::max_value() as u64 {
return Err(io::Error::new(io::ErrorKind::Other, "file is larger than address space"));
}
let mut platform_data = PlatformData {
file: file,
mapping_handle: ptr::null_mut(),
};
if length == 0 {
return Ok((ptr::null(), 0, platform_data));
}
platform_data.mapping_handle = unsafe {
winapi::um::memoryapi::CreateFileMappingW(
file_handle as *mut winapi::ctypes::c_void,
ptr::null_mut(), winapi::um::winnt::PAGE_READONLY, 0, 0, ptr::null_mut() )
};
if platform_data.mapping_handle == ptr::null_mut() {
return Err(io::Error::last_os_error());
}
let result = unsafe {
winapi::um::memoryapi::MapViewOfFile(
platform_data.mapping_handle,
winapi::um::memoryapi::FILE_MAP_READ, 0, 0, length as winapi::shared::basetsd::SIZE_T )
};
if result == ptr::null_mut() {
Err(io::Error::last_os_error())
} else {
Ok((result as *const u8, length as usize, platform_data))
}
}
pub fn unmap_file(buffer: *const u8, _length: usize) {
let success = unsafe {
winapi::um::memoryapi::UnmapViewOfFile(buffer as *mut winapi::ctypes::c_void)
};
assert!(success != 0);
}
pub fn get_resident(_buffer: *const u8, _length: usize, residency: &mut [bool]) {
for x in residency {
*x = true;
}
}
pub fn prefetch(buffer: *const u8, length: usize) {
let mut entry = winapi::um::memoryapi::WIN32_MEMORY_RANGE_ENTRY {
VirtualAddress: buffer as *mut winapi::ctypes::c_void,
NumberOfBytes: length as winapi::shared::basetsd::SIZE_T,
};
unsafe {
let current_process_handle = winapi::um::processthreadsapi::GetCurrentProcess();
winapi::um::memoryapi::PrefetchVirtualMemory(
current_process_handle, 1, &mut entry, 0 );
}
}
pub fn get_page_size() -> usize {
let mut sysinfo: winapi::um::sysinfoapi::SYSTEM_INFO = unsafe { mem::zeroed() };
unsafe { winapi::um::sysinfoapi::GetSystemInfo(&mut sysinfo); }
sysinfo.dwPageSize as usize
}