dope 0.12.0

The manifold runtime
Documentation
use std::io;
use std::mem::MaybeUninit;
use std::os::fd::{AsRawFd, RawFd};
use std::ptr::NonNull;

pub(in crate::manifold::file) mod table;

use super::source::Source;
use dope_core::backend::Backend;
use dope_core::backend::RawSqe;
use dope_core::driver::token::Token;
use dope_core::io::file::OpenPath;
use dope_core::platform::Platform;
use std::io::Error;
use std::io::ErrorKind;

type StatBuf = <Backend as Platform>::StatBuf;

pub(super) struct OpenRequest {
    path: OpenPath,
}

impl OpenRequest {
    pub(super) fn new(path: OpenPath) -> Self {
        Self { path }
    }

    pub(super) fn submission(&self, flags: i32, token: Token) -> RawSqe {
        self.path.open_at(flags, token)
    }
}

enum StatSource<'d> {
    Path(OpenPath),
    Fd(Source<'d>),
}

pub(super) struct StatRequest<'d> {
    source: StatSource<'d>,
    output: MaybeUninit<StatBuf>,
}

impl<'d> StatRequest<'d> {
    pub(super) fn path(path: OpenPath) -> Self {
        Self {
            source: StatSource::Path(path),
            output: MaybeUninit::zeroed(),
        }
    }

    pub(super) fn fd(source: Source<'d>) -> Self {
        Self {
            source: StatSource::Fd(source),
            output: MaybeUninit::zeroed(),
        }
    }

    pub(super) fn submission(&mut self, token: Token) -> RawSqe {
        let output = self.output.as_mut_ptr();
        match &self.source {
            StatSource::Path(path) => RawSqe::stat_path(path.as_ptr(), output, token),
            StatSource::Fd(fd) => RawSqe::stat_fd(fd.as_raw_fd(), output, token),
        }
    }

    pub(super) fn complete(&mut self) -> StatBuf {
        unsafe { self.output.assume_init_read() }
    }
}

pub(super) struct ReadRegion {
    ptr: NonNull<MaybeUninit<u8>>,
    len: u32,
}

impl ReadRegion {
    pub(super) fn new(buffer: &mut Vec<u8>) -> Option<Self> {
        let len = buffer.len().min(u32::MAX as usize) as u32;
        (len != 0).then(|| Self {
            ptr: unsafe { NonNull::new_unchecked(buffer.as_mut_ptr().cast()) },
            len,
        })
    }

    pub(super) fn submission(self, fd: RawFd, offset: u64, token: Token) -> (RawSqe, Self) {
        let sqe = RawSqe::read_raw(
            fd,
            self.ptr.as_ptr().cast(),
            self.len as usize,
            offset,
            token,
        );
        (sqe, self)
    }

    pub(super) fn commit(self, buffer: &mut Vec<u8>, amount: u32) -> io::Result<()> {
        if amount > self.len {
            return Err(Error::new(
                ErrorKind::InvalidData,
                "dope::file: completion exceeded its prepared read region",
            ));
        }
        if buffer.as_mut_ptr().cast() != self.ptr.as_ptr() || buffer.len() < self.len as usize {
            return Err(Error::new(
                ErrorKind::InvalidData,
                "dope::file: prepared read buffer changed before completion",
            ));
        }
        Ok(())
    }
}