dope-core 0.15.1

The manifold runtime
Documentation
use std::process;

use crate::{backend::fixed, driver, io::fd::handles};

#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Outbound<'d>(driver::Reference<'d>);

impl<'d> Outbound<'d> {
    pub(in crate::driver) const fn new(driver: driver::Reference<'d>) -> Self {
        Self(driver)
    }

    pub(in crate::driver) fn is_unopened(
        self,
        key: driver::OutboundKey,
        slot: handles::FixedSlot,
    ) -> bool {
        self.0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .is_unopened(key, slot)
    }

    pub(crate) fn begin_outbound_create(
        self,
        key: driver::OutboundKey,
        slot: handles::FixedSlot,
    ) -> bool {
        self.0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .begin_create(key, slot)
    }

    pub(crate) fn begin_outbound_create_for(self, slot: handles::FixedSlot) -> bool {
        let driver::FixedOwner::Outbound(key) = self.0.files().fixed_owner(slot) else {
            return false;
        };
        self.begin_outbound_create(key, slot)
    }

    pub(crate) fn begin_outbound_close(
        self,
        key: driver::OutboundKey,
        slot: handles::FixedSlot,
    ) -> driver::CloseDisposition<'d> {
        let result = self
            .0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .begin_close(key, slot);
        match result {
            Ok((true, None)) => driver::CloseDisposition::Submit(driver::Close::tracked(slot)),
            Ok((false, slots)) => {
                driver::CloseDisposition::NoSubmit(slots.map(driver::RetiredSlots::new))
            }
            Ok((true, Some(_))) | Err(()) => process::abort(),
        }
    }

    pub(crate) fn close_disposition(
        self,
        slot: handles::FixedSlot,
        outbound: Option<driver::OutboundKey>,
    ) -> driver::CloseDisposition<'d> {
        match outbound {
            Some(outbound) => self.begin_outbound_close(outbound, slot),
            None => driver::CloseDisposition::Submit(driver::Close::untracked(slot)),
        }
    }

    pub(crate) fn complete_outbound_close(
        self,
        slot: handles::FixedSlot,
    ) -> Option<driver::RetiredSlots<'d>> {
        let result = self
            .0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .complete_close(slot);
        match result {
            Ok(slots) => slots.map(driver::RetiredSlots::new),
            Err(()) => process::abort(),
        }
    }

    pub(crate) fn release_outbound_slot(
        self,
        key: driver::OutboundKey,
        slot: handles::FixedSlot,
    ) -> Option<driver::RetiredSlots<'d>> {
        let result = self
            .0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .release_unopened(key, slot);
        match result {
            Ok(slots) => slots.map(driver::RetiredSlots::new),
            Err(()) => process::abort(),
        }
    }

    pub(crate) fn release_outbound_slot_for(
        self,
        slot: handles::FixedSlot,
    ) -> Option<driver::RetiredSlots<'d>> {
        let driver::FixedOwner::Outbound(key) = self.0.files().fixed_owner(slot) else {
            process::abort();
        };
        self.release_outbound_slot(key, slot)
    }

    pub(crate) fn complete_outbound_create_success(
        self,
        slot: handles::FixedSlot,
    ) -> driver::CreateSuccess<'d> {
        use crate::driver::ops::access::files::leases::CreateTransition;

        let result = self
            .0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .complete_create_success(slot);
        match result {
            Ok(CreateTransition::Deliver(key)) => driver::CreateSuccess::Deliver(key),
            Ok(CreateTransition::Close) => {
                driver::CreateSuccess::Close(driver::Close::tracked(slot))
            }
            Err(()) => process::abort(),
        }
    }

    pub(crate) fn complete_outbound_create_failure(
        self,
        slot: handles::FixedSlot,
    ) -> Option<driver::RetiredSlots<'d>> {
        let result = self
            .0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .complete_create_failure(slot);
        match result {
            Ok(slots) => slots.map(driver::RetiredSlots::new),
            Err(()) => process::abort(),
        }
    }

    pub(crate) fn activate_outbound(
        self,
        key: driver::OutboundKey,
        slot: handles::FixedSlot,
    ) -> bool {
        self.0
            .shared
            .files
            .leases
            .borrow_mut()
            .issues()
            .activate(key, slot)
    }

    pub(crate) fn release_outbound_owner(
        self,
        key: driver::OutboundKey,
    ) -> Option<driver::RetiredSlots<'d>> {
        self.0
            .shared
            .files
            .leases
            .borrow_mut()
            .release_owner(key)
            .map(driver::RetiredSlots::new)
    }

    pub(crate) fn take_retired_slots(
        self,
        retired: driver::RetiredSlots<'d>,
    ) -> fixed::Reservation<'d> {
        self.0
            .shared
            .files
            .leases
            .borrow_mut()
            .take_retired(retired)
    }
}

const _: () = assert!(
    std::mem::size_of::<Outbound<'static>>() == std::mem::size_of::<driver::Reference<'static>>()
);