use std::{
    io,
    ops::{Deref, DerefMut},
    os::fd::{AsRawFd, OwnedFd, RawFd},
};

use crate::sys::{
    FileMapping as SysFileMapping, FileMappingImpl, SharedMemory as SysSharedMemory,
    SharedMemoryImpl,
};

pub struct SharedMemory(SharedMemoryImpl);
pub struct FileMapping(FileMappingImpl);

impl SharedMemory {
    pub fn new(size: usize) -> io::Result<Self> {
        SharedMemoryImpl::new(size).map(Self)
    }

    pub fn map(self) -> io::Result<FileMapping> {
        self.0.map().map(FileMapping)
    }
}

impl AsRawFd for SharedMemory {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}

impl FileMapping {
    pub fn map<F: Into<OwnedFd>>(file: F, size: usize, write: bool) -> io::Result<Self> {
        FileMappingImpl::map(file, size, write).map(Self)
    }
}

impl Deref for FileMapping {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        self.0.deref()
    }
}

impl DerefMut for FileMapping {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.0.deref_mut()
    }
}

impl AsRawFd for FileMapping {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}
