use std::error::Error;
use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum OffloadError {
Closed,
WorkerLost,
Injected,
}
impl fmt::Display for OffloadError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let message = match self {
Self::Closed => "compute pool is closed",
Self::WorkerLost => "compute worker produced no result",
Self::Injected => "injected compute failure",
};
f.write_str(message)
}
}
impl Error for OffloadError {}
#[allow(async_fn_in_trait)]
pub trait Offload: Clone + 'static {
async fn run<F, T>(&self, task: F) -> Result<T, OffloadError>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct InlineOffload;
impl Offload for InlineOffload {
async fn run<F, T>(&self, task: F) -> Result<T, OffloadError>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
Ok(task())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn inline_offload_runs_the_closure_and_returns_its_value() {
assert_eq!(InlineOffload.run(|| 6 * 7).await, Ok(42));
}
#[test]
fn offload_errors_describe_themselves() {
assert_eq!(OffloadError::Closed.to_string(), "compute pool is closed");
assert_eq!(OffloadError::WorkerLost.to_string(), "compute worker produced no result");
assert_eq!(OffloadError::Injected.to_string(), "injected compute failure");
}
}