rts-alloc 4.0.0

Shared memory allocator intended for small frequent allocations
Documentation
use crate::error::Error;
use core::ffi::c_void;
use std::fs::File;

#[cfg(unix)]
pub(crate) fn map_file(file: &File, size: usize) -> Result<*mut c_void, Error> {
    use std::os::fd::AsRawFd;

    let mmap = unsafe {
        libc::mmap(
            core::ptr::null_mut(),
            size,
            libc::PROT_READ | libc::PROT_WRITE,
            libc::MAP_SHARED,
            file.as_raw_fd(),
            0,
        )
    };

    if mmap == libc::MAP_FAILED {
        return Err(Error::MmapError(std::io::Error::last_os_error()));
    }

    Ok(mmap)
}

#[cfg(windows)]
pub(crate) fn map_file(file: &File, size: usize) -> Result<*mut c_void, Error> {
    use std::os::windows::io::AsRawHandle;
    use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
    use windows_sys::Win32::System::Memory::{
        CreateFileMappingW, MapViewOfFile, FILE_MAP_ALL_ACCESS, PAGE_READWRITE,
    };

    let size_u64 = u64::try_from(size).map_err(|_| Error::InvalidFileSize)?;
    let size_high = (size_u64 >> 32) as u32;
    let size_low = size_u64 as u32;

    let mapping = unsafe {
        CreateFileMappingW(
            file.as_raw_handle() as HANDLE,
            core::ptr::null(),
            PAGE_READWRITE,
            size_high,
            size_low,
            core::ptr::null(),
        )
    };

    if mapping.is_null() {
        return Err(Error::MmapError(std::io::Error::last_os_error()));
    }

    let mmap = unsafe { MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, size) };
    if mmap.Value.is_null() {
        let err = Error::MmapError(std::io::Error::last_os_error());
        unsafe { CloseHandle(mapping) };
        Err(err)
    } else {
        unsafe { CloseHandle(mapping) };
        Ok(mmap.Value.cast())
    }
}

#[cfg(unix)]
pub(crate) fn unmap_file(ptr: *mut c_void, size: usize) -> Result<(), Error> {
    let rc = unsafe { libc::munmap(ptr, size) };
    if rc != 0 {
        return Err(Error::MmapError(std::io::Error::last_os_error()));
    }
    Ok(())
}

#[cfg(windows)]
pub(crate) fn unmap_file(ptr: *mut c_void, _size: usize) -> Result<(), Error> {
    use windows_sys::Win32::System::Memory::{UnmapViewOfFile, MEMORY_MAPPED_VIEW_ADDRESS};

    let rc = unsafe { UnmapViewOfFile(MEMORY_MAPPED_VIEW_ADDRESS { Value: ptr.cast() }) };
    if rc == 0 {
        return Err(Error::MmapError(std::io::Error::last_os_error()));
    }
    Ok(())
}