dope-manifold 0.41.0

Owned application and service composition for dope
use dope_core::{
    driver::{retained::flight, route::kind},
    io::transfer,
};
use o3::depot::queue::ring::inline;

use crate::file::appender::{Failure, Storage};

pub(in crate::file) enum InFlight<'p, 'd, const N: usize> {
    Submitted {
        pending: Pending<'p, N>,
        flight: flight::Flight<'d, kind::Write>,
    },
    Rejected {
        pending: Pending<'p, N>,
    },
}
pub(in crate::file) struct Pending<'p, const N: usize> {
    block: inline::Lease<'p, Vec<u8>, N>,
    remaining: transfer::Len,
}
pub(in crate::file) struct Queue<'p, 'd, const N: usize, const B: usize> {
    pub(super) storage: &'p Storage<N, B>,
    pub(super) current: Option<inline::Lease<'p, Vec<u8>, N>>,
    pub(super) in_flight: Option<InFlight<'p, 'd, N>>,
}
impl<const N: usize, const B: usize> Queue<'_, '_, N, B> {
    pub(super) fn discard(&mut self) {
        if let Some(current) = self.current.take() {
            release(current);
        }
        while let Some((block, ())) = self.storage.pool.pop_front() {
            release(block);
        }
    }
}

impl<const N: usize, const B: usize> Drop for Queue<'_, '_, N, B> {
    fn drop(&mut self) {
        let pending = self.in_flight.is_some()
            || !self.storage.pool.is_empty()
            || self
                .current
                .as_ref()
                .is_some_and(|block| !block.get().is_empty());
        if pending && self.storage.failure().is_none() {
            self.storage.failure.set(Some(Failure::Cancelled));
        }
        if let Some(active) = self.in_flight.take() {
            active.cancel().release();
        }
        self.discard();
    }
}

fn release<const N: usize>(mut block: inline::Lease<'_, Vec<u8>, N>) {
    block.get_mut().clear();
    block.release();
}
impl<'p, 'd, const N: usize> InFlight<'p, 'd, N> {
    pub(super) fn cancel(self) -> Pending<'p, N> {
        match self {
            Self::Submitted { pending, .. } | Self::Rejected { pending } => pending,
        }
    }
}
impl<'p, const N: usize> Pending<'p, N> {
    pub(super) fn new(block: inline::Lease<'p, Vec<u8>, N>) -> Self {
        let remaining = transfer::Len::prefix(block.get().len(), transfer::Len::MAX);
        Self { block, remaining }
    }
    pub(super) fn bytes(&self) -> &[u8] {
        self.block.get()
    }
    pub(super) fn release(self) {
        release(self.block);
    }
    pub(super) const fn remaining(&self) -> transfer::Len {
        self.remaining
    }
    pub(in crate::file) const fn is_complete(&self) -> bool {
        self.remaining.is_zero()
    }
    pub(in crate::file) fn advance(&mut self, amount: transfer::Len) {
        self.remaining = self.remaining.abs_diff(amount);
    }
}