use std::{ ffi::c_void, io, ops::{Deref, DerefMut}, os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd}, ptr::null_mut, }; use crate::sys; pub struct SharedMemoryImpl { fd: OwnedFd, size: usize, } pub struct FileMappingImpl { fd: OwnedFd, pointer: *mut c_void, size: usize, } impl sys::SharedMemory for SharedMemoryImpl { type Mapping = FileMappingImpl; fn map(self) -> io::Result { ::map(self.fd, self.size) } fn new(size: usize) -> io::Result { let fd = unsafe { libc::memfd_create(c"cross-shm".as_ptr(), libc::MFD_CLOEXEC) }; if fd < 0 { return Err(io::Error::last_os_error()); } let fd = unsafe { OwnedFd::from_raw_fd(fd) }; if unsafe { libc::ftruncate(fd.as_raw_fd(), size as i64) } != 0 { return Err(io::Error::last_os_error()); } Ok(Self { fd, size }) } } impl AsRawFd for SharedMemoryImpl { fn as_raw_fd(&self) -> RawFd { self.fd.as_raw_fd() } } impl sys::FileMapping for FileMappingImpl { fn map>(file: F, size: usize) -> io::Result { let fd: OwnedFd = file.into(); let pointer = unsafe { libc::mmap( null_mut(), size, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED, fd.as_raw_fd(), 0, ) }; if pointer == libc::MAP_FAILED { return Err(io::Error::last_os_error()); } Ok(Self { fd, pointer, size }) } } impl Drop for FileMappingImpl { fn drop(&mut self) { unsafe { libc::munmap(self.pointer, self.size); } } } impl Deref for FileMappingImpl { type Target = [u8]; fn deref(&self) -> &Self::Target { unsafe { core::slice::from_raw_parts(self.pointer.cast(), self.size) } } } impl DerefMut for FileMappingImpl { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { core::slice::from_raw_parts_mut(self.pointer.cast(), self.size) } } } impl AsRawFd for FileMappingImpl { fn as_raw_fd(&self) -> RawFd { self.fd.as_raw_fd() } }