use std::io;
use std::os::windows::io::OwnedHandle;
use std::time::Duration;
use win_sync_sys::Event;
use windows_ioring_sys::{IoBuf, IoBufMut};
use crate::windows_backend::WindowsBackend;
use crate::windows_backend::pool::{PoolDelivery, PoolEngine, Shared};
use crate::windows_backend::signalled::SignalledDelivery;
use durable_ioring::EpochId;
use durable_ioring::StampClock;
use durable_ioring::driver::EngineGuard;
use durable_ioring::driver::{Pumped, PumpedDelivery};
pub(crate) enum Delivery<E, B, C, K, R>
where
E: EpochId + 'static,
B: IoBuf,
R: IoBufMut,
K: StampClock,
{
Pool(PoolDelivery<E, B, C, K, R>),
Pumped(PumpedDelivery<E, WindowsBackend<B, R>, C, K>),
Signalled(SignalledDelivery<E, B, C, K, R>),
}
impl<E, B, C, K, R> Delivery<E, B, C, K, R>
where
E: EpochId + 'static,
B: IoBuf,
R: IoBufMut,
K: StampClock,
{
pub(crate) fn engine(&self) -> EngineGuard<'_, PoolEngine<E, B, C, K, R>> {
match self {
Self::Pool(pool) => pool.engine(),
Self::Pumped(pumped) => pumped.engine(),
Self::Signalled(signalled) => signalled.engine(),
}
}
pub(crate) fn shared(&self) -> Shared<E, B, C, K, R> {
match self {
Self::Pool(pool) => pool.shared(),
Self::Pumped(pumped) => pumped.shared(),
Self::Signalled(signalled) => signalled.shared(),
}
}
pub(crate) fn into_engine(self) -> PoolEngine<E, B, C, K, R> {
match self {
Self::Pool(pool) => pool.into_engine(),
Self::Pumped(pumped) => pumped.into_engine(),
Self::Signalled(signalled) => signalled.into_engine(),
}
}
pub(crate) fn pump(&mut self, timeout: Option<Duration>) -> Option<Pumped> {
match self {
Self::Pool(_) => None,
Self::Pumped(pumped) => Some(pumped.pump(timeout)),
Self::Signalled(signalled) => Some(signalled.pump(timeout)),
}
}
pub(crate) fn signal(&self) -> Option<io::Result<Event>> {
match self {
Self::Signalled(signalled) => Some(signalled.signal()),
Self::Pool(_) | Self::Pumped(_) => None,
}
}
pub(crate) fn completion_event(&self) -> Option<io::Result<OwnedHandle>> {
match self {
Self::Pumped(pumped) => Some(pumped.engine().backend.completion_wait_handle()),
Self::Pool(_) | Self::Signalled(_) => None,
}
}
#[cfg(test)]
pub(crate) fn is_pumped(&self) -> bool {
matches!(self, Self::Pumped(_))
}
#[cfg(test)]
pub(crate) fn is_signalled(&self) -> bool {
matches!(self, Self::Signalled(_))
}
}