use std::{
    io,
    ops::{Deref, DerefMut},
    os::{
        fd::{AsRawFd, OwnedFd, RawFd},
        yggdrasil::io::{mapping as map, shared_memory as shm},
    },
};

use crate::sys::{FileMapping, SharedMemory};

pub struct SharedMemoryImpl {
    inner: shm::SharedMemory,
}

pub struct FileMappingImpl {
    inner: map::FileMapping<'static>,
}

impl SharedMemory for SharedMemoryImpl {
    type Mapping = FileMappingImpl;

    fn new(size: usize) -> io::Result<Self> {
        let inner = shm::SharedMemory::new(size)?;
        Ok(Self { inner })
    }

    fn map(self) -> io::Result<Self::Mapping> {
        let inner = self.inner.into_mapping()?;
        Ok(FileMappingImpl { inner })
    }
}

impl AsRawFd for SharedMemoryImpl {
    fn as_raw_fd(&self) -> RawFd {
        self.inner.as_raw_fd()
    }
}

impl FileMapping for FileMappingImpl {
    fn map<F: Into<OwnedFd>>(file: F, size: usize, _write: bool) -> io::Result<Self> {
        let inner = map::FileMapping::new(file, 0, size)?;
        Ok(Self { inner })
    }
}

impl AsRawFd for FileMappingImpl {
    fn as_raw_fd(&self) -> RawFd {
        self.inner.as_raw_fd()
    }
}

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

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

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