dope-net 0.26.0

Owned network transports for dope
Documentation
use std::{cell, mem};

use crate::link::slot::types::{CloseGate, Readiness};

#[derive(Clone, Copy)]
enum Phase {
    Open,
    Draining,
    Closing,
}

#[derive(Clone, Copy)]
#[repr(u8)]
enum Fact {
    Discarded = 1 << 0,
    GracefulRequested = 1 << 1,
    GracefulSealed = 1 << 2,
    SendCancelRejected = 1 << 3,
    SendCancelRequested = 1 << 4,
    WriteShutdownRequested = 1 << 5,
    WriteShutdownSubmitted = 1 << 6,
    WriteShutdownComplete = 1 << 7,
}

#[repr(transparent)]
struct Flags(u8);

pub(in crate::link) struct State {
    phase: cell::Cell<Phase>,
    pub(in crate::link) close: Close,
    waiting: bool,
}

impl State {
    pub(super) fn new() -> Self {
        Self {
            phase: cell::Cell::new(Phase::Open),
            close: Close::new(),
            waiting: false,
        }
    }

    pub(in crate::link) fn discard(&mut self) {
        self.waiting = false;
        self.close.flags.set(Fact::Discarded);
        self.phase.set(Phase::Closing);
    }

    pub(in crate::link) fn is_waiting(&self) -> bool {
        self.waiting
    }

    pub(in crate::link) fn wait_send(&mut self, waiting: bool) {
        self.waiting = waiting;
    }

    pub(in crate::link) fn is_closing(&self) -> bool {
        matches!(self.phase.get(), Phase::Closing)
    }

    pub(in crate::link) fn close(&self) {
        self.phase.set(Phase::Closing);
    }

    pub(in crate::link) fn is_draining(&self) -> bool {
        matches!(self.phase.get(), Phase::Draining)
    }

    pub(in crate::link) fn drain(&mut self) {
        if matches!(self.phase.get(), Phase::Open) {
            self.phase.set(Phase::Draining);
        }
    }

    pub(in crate::link) fn close_due(&self, sending: bool, gate: CloseGate) -> Readiness {
        if sending {
            return Readiness::Waiting;
        }
        match self.phase.get() {
            Phase::Open => Readiness::Waiting,
            Phase::Draining => match gate {
                CloseGate::Immediate => Readiness::Due,
                CloseGate::Deferred => Readiness::Waiting,
            },
            Phase::Closing => Readiness::Due,
        }
    }
}

pub(in crate::link) struct Close {
    flags: Flags,
    pub(in crate::link) owner: Ownership,
}

pub(in crate::link) enum Claim {
    Ready(Authority),
    Unavailable,
}

pub(in crate::link) enum Ownership {
    Held,
    Released,
    Claimed,
}

#[must_use = "claimed owner authority must retire the slot or be restored"]
pub(in crate::link) struct Authority(());

#[must_use]
pub(in crate::link) enum Request {
    Ready,
    Discarded,
    Duplicate,
}

#[must_use]
pub(in crate::link) enum Seal {
    Ready,
    Missing,
    Duplicate,
}

#[must_use]
pub(in crate::link) enum Shutdown {
    Pending,
    Ready,
    Submitted,
    Complete,
}

impl Close {
    const fn new() -> Self {
        Self {
            flags: Flags::EMPTY,
            owner: Ownership::Held,
        }
    }

    pub(in crate::link) fn is_discarded(&self) -> bool {
        self.flags.contains(Fact::Discarded)
    }

    pub(in crate::link) fn can_cancel(&self) -> bool {
        self.flags.contains(Fact::Discarded)
            && !self.flags.contains(Fact::SendCancelRequested)
            && !self.flags.contains(Fact::SendCancelRejected)
    }

    pub(in crate::link) fn deny_cancel(&mut self) {
        self.flags.set(Fact::SendCancelRejected);
    }

    pub(in crate::link) fn mark_cancel(&mut self) {
        self.flags.set(Fact::SendCancelRequested);
    }

    pub(in crate::link) fn request(&mut self) -> Request {
        if self.flags.contains(Fact::Discarded) {
            return Request::Discarded;
        }
        if self.flags.contains(Fact::GracefulRequested) {
            return Request::Duplicate;
        }
        self.flags.set(Fact::GracefulRequested);
        Request::Ready
    }

    pub(in crate::link) fn check_seal(&self) -> Seal {
        if !self.flags.contains(Fact::GracefulRequested) {
            return Seal::Missing;
        }
        if self.flags.contains(Fact::GracefulSealed) {
            return Seal::Duplicate;
        }
        Seal::Ready
    }

    pub(in crate::link) fn seal(&mut self) {
        self.flags.set(Fact::GracefulSealed);
    }

    pub(in crate::link) fn shutdown(&mut self) {
        if self.flags.contains(Fact::Discarded) || self.flags.contains(Fact::WriteShutdownRequested)
        {
            return;
        }
        self.flags.set(Fact::WriteShutdownRequested);
    }

    pub(in crate::link) fn is_shutting(&self) -> bool {
        self.flags.contains(Fact::WriteShutdownRequested)
            && !self.flags.contains(Fact::WriteShutdownComplete)
    }

    pub(in crate::link) fn has_shutdown(&self) -> bool {
        self.flags.contains(Fact::WriteShutdownRequested)
    }

    pub(in crate::link) fn take_write(&self) -> Shutdown {
        if !self.flags.contains(Fact::WriteShutdownRequested)
            || !self.flags.contains(Fact::GracefulSealed)
        {
            return Shutdown::Pending;
        }
        if self.flags.contains(Fact::WriteShutdownComplete) {
            return Shutdown::Complete;
        }
        if self.flags.contains(Fact::WriteShutdownSubmitted) {
            return Shutdown::Submitted;
        }
        Shutdown::Ready
    }

    pub(in crate::link) fn arm_write(&mut self) {
        self.flags.set(Fact::WriteShutdownSubmitted);
    }

    pub(in crate::link) fn finish_write(&mut self) {
        self.flags.set(Fact::WriteShutdownComplete);
    }
}

impl Flags {
    const EMPTY: Self = Self(0);

    fn contains(&self, fact: Fact) -> bool {
        self.0 & fact as u8 != 0
    }

    fn set(&mut self, fact: Fact) {
        self.0 |= fact as u8;
    }
}

impl Ownership {
    pub(in crate::link) fn release(&mut self) {
        if matches!(self, Ownership::Held) {
            *self = Ownership::Released;
        }
    }

    pub(in crate::link) fn claim(&mut self) -> Claim {
        match mem::replace(self, Ownership::Claimed) {
            Ownership::Released => Claim::Ready(Authority(())),
            state => {
                *self = state;
                Claim::Unavailable
            }
        }
    }

    pub(in crate::link) fn restore(&mut self, proof: Authority) {
        let Authority(()) = proof;
        *self = Ownership::Released;
    }
}

const _: () = {
    use std::mem;

    assert!(mem::size_of::<Close>() == mem::size_of::<Flags>() + mem::size_of::<Ownership>());
    assert!(mem::align_of::<Close>() == mem::align_of::<u8>());
    assert!(
        mem::size_of::<State>()
            == mem::size_of::<cell::Cell<Phase>>()
                + mem::size_of::<Close>()
                + mem::size_of::<bool>()
    );
    assert!(mem::align_of::<State>() == mem::align_of::<u8>());
    assert!(mem::size_of::<Request>() == 1);
    assert!(mem::size_of::<Seal>() == 1);
    assert!(mem::size_of::<Shutdown>() == 1);
};