dope-uring 0.39.0

Owned io_uring backend for dope
Documentation
use std::mem;

use dope_sys::{
    io::reactor::complete::{
        self, Decode, Flags as _, Outcome as _, Record as _,
        flags::{self, Meta as _},
    },
    probe::{self, Check, Failure},
};

use crate::{Observed, reactor::cq};

pub struct Outcome<T, P> {
    token: T,
    outcome: cq::Outcome,
    meta: cq::Meta,
    probe: P,
}

impl<T: complete::raw::Token, P: Copy> probe::Outcome for Outcome<T, P> {
    type Parts = complete::Parts<T, cq::Outcome, cq::Flags>;
    type Value = cq::Value;
    type Meta = cq::Meta;
    type Probe = P;
    type Observation = Observed<T>;

    fn new(parts: Self::Parts, probe: P) -> Result<Self, Failure<P, Observed<T>>> {
        let meta = match parts.flags.decode() {
            Ok(meta) => meta,
            Err(invalid) => {
                let observed = Observed::new(parts.token, parts.outcome, invalid.into());
                return Err(Failure::new(probe, Check::InvalidFlags(observed)));
            }
        };
        Ok(Self {
            token: parts.token,
            outcome: parts.outcome,
            meta,
            probe,
        })
    }

    fn success(&self) -> Result<cq::Value, Failure<P, Observed<T>>> {
        match self.outcome.decode() {
            Decode::Value(value) => Ok(value),
            Decode::Error(_) => Err(Failure::new(self.probe, Check::Rejected(self.observed()))),
            Decode::Invalid(_) => Err(self.unexpected()),
        }
    }

    fn zero(self) -> Result<(), Failure<P, Observed<T>>> {
        let result = self.success()?;
        if result.get() == 0 {
            Ok(())
        } else {
            Err(self.unexpected())
        }
    }

    fn canceled(self) -> Result<(), Failure<P, Observed<T>>> {
        if self.outcome == cq::Outcome::from_error(dope_sys::Errno::CANCELED)
            && matches!(self.meta.flow(), flags::Flow::Last)
        {
            Ok(())
        } else {
            Err(self.unexpected())
        }
    }

    fn cancel(self) -> Result<(), Failure<P, Observed<T>>> {
        if self.outcome == cq::Outcome::from_error(dope_sys::Errno::CANCELED)
            && self.meta.buffer().is_none()
        {
            Ok(())
        } else {
            Err(self.nonterminal())
        }
    }

    fn probe(&self) -> P {
        self.probe
    }

    fn meta(&self) -> cq::Meta {
        self.meta
    }

    fn unexpected(&self) -> Failure<P, Observed<T>> {
        Failure::new(self.probe, Check::Unexpected(self.observed()))
    }

    fn nonterminal(&self) -> Failure<P, Observed<T>> {
        Failure::new(self.probe, Check::Nonterminal(self.observed()))
    }
}

impl<T: Copy, P: Copy> Outcome<T, P> {
    fn observed(&self) -> Observed<T> {
        Observed::new(self.token, self.outcome, self.meta.into())
    }
}

const _: () = {
    assert!(mem::size_of::<Outcome<u64, u8>>() == 3 * mem::size_of::<u64>());
    assert!(mem::align_of::<Outcome<u64, u8>>() == mem::align_of::<u64>());
};