dope-net 0.15.0

The manifold runtime
Documentation
use std::num;

use dope_core::{
    driver::{self, flight, retained, route},
    io::fd::handles,
};

use crate::{
    link,
    link::engine::lifecycle,
    wire::{reclaim, send},
};

pub(in crate::link) struct Sending {
    limit: Option<num::NonZeroU32>,
}

pub(in crate::link) struct Submission<'a, 'd> {
    sending: &'a mut Sending,
    flights: &'a mut super::Flights<'d>,
    lifecycle: &'a mut lifecycle::Lifecycle,
}

impl Sending {
    pub(super) fn new() -> Self {
        Self { limit: None }
    }

    pub(in crate::link) fn is_inflight(&self) -> bool {
        self.limit.is_some()
    }

    pub(in crate::link) fn complete(
        &mut self,
        flights: &mut super::Flights<'_>,
        lifecycle: &mut lifecycle::Lifecycle,
        bytes: u32,
    ) -> Option<send::Sent> {
        use crate::wire::send::Sent;
        if bytes > self.limit?.get() {
            lifecycle.abort();
            self.done(flights);
            return None;
        }
        self.done(flights);
        Some(Sent::new(bytes))
    }

    pub(in crate::link) fn done(&mut self, flights: &mut super::Flights<'_>) {
        self.limit = None;
        if let Some(flight) = flights.send.take() {
            let _ = flight.complete();
        }
    }

    fn submit<'d, Tag: route::Tag>(
        driver: &mut retained::Context<'_, '_, 'd>,
        slots: &flight::Slots<'d, Tag>,
        fd: &handles::Descriptor<'d>,
        target: route::Target<'d, Tag>,
        send: &impl link::raw::Send,
    ) -> Result<flight::Flight<'d>, driver::SubmitError> {
        send.submit_retained(fd, target, slots, driver)
    }

    pub(in crate::link) fn submission<'a, 'd>(
        &'a mut self,
        flights: &'a mut super::Flights<'d>,
        lifecycle: &'a mut lifecycle::Lifecycle,
    ) -> Submission<'a, 'd> {
        Submission {
            sending: self,
            flights,
            lifecycle,
        }
    }
}

impl<'d> Submission<'_, 'd> {
    pub(in crate::link) fn take_pending_graceful(&mut self) -> bool {
        self.lifecycle.take_graceful(self.sending.is_inflight())
    }

    pub(in crate::link) fn submit_prepared<Tag: route::Tag, P: reclaim::Policy>(
        &mut self,
        fd: &handles::Descriptor<'d>,
        slots: &flight::Slots<'d, Tag>,
        driver: &mut retained::Context<'_, '_, 'd>,
        target: route::Target<'d, Tag>,
        prepared: send::Prepared<'_, P>,
    ) -> send::Outcome<P> {
        use crate::wire::send::Payload;
        let (payload, consumed, close_after) = prepared.into_parts();
        if close_after {
            self.lifecycle.set_close_after();
        }
        if self.sending.is_inflight() {
            return send::Outcome::idle(consumed);
        }
        let (flight, limit) = match payload {
            Payload::Empty => return send::Outcome::idle(consumed),
            Payload::Single(buf) if buf.is_empty() => return send::Outcome::idle(consumed),
            Payload::Single(buf) => {
                let Ok(limit) = u32::try_from(buf.len()) else {
                    return send::Outcome::rejected(consumed);
                };
                let Some(limit) = num::NonZeroU32::new(limit) else {
                    return send::Outcome::idle(consumed);
                };
                let Ok(flight) = Sending::submit(driver, slots, fd, target, &buf) else {
                    return send::Outcome::rejected(consumed);
                };
                (flight, limit)
            }
            Payload::Vectored(vectored) if vectored.is_empty() => {
                return send::Outcome::idle(consumed);
            }
            Payload::Vectored(vectored) => {
                let Ok(limit) = u32::try_from(vectored.bytes()) else {
                    return send::Outcome::rejected(consumed);
                };
                let Some(limit) = num::NonZeroU32::new(limit) else {
                    return send::Outcome::idle(consumed);
                };
                let Ok(flight) = Sending::submit(driver, slots, fd, target, &vectored) else {
                    return send::Outcome::rejected(consumed);
                };
                (flight, limit)
            }
        };
        self.sending.limit = Some(limit);
        self.flights.send = Some(flight);
        send::Outcome::submitted(consumed)
    }
}

impl Sending {
    pub(in crate::link) fn cancel_flight<'a, 'd>(
        &mut self,
        flights: &'a mut super::Flights<'d>,
    ) -> Option<&'a mut flight::Flight<'d>> {
        flights.send.as_mut()
    }
}