Skip to main content

crux_core/core/
resolve.rs

1use thiserror::Error;
2
3// used in docs/internals/runtime.md
4// ANCHOR: resolve
5type ResolveOnce<Out> = Box<dyn FnOnce(Out) + Send>;
6type ResolveMany<Out> = Box<dyn Fn(Out) -> Result<(), ()> + Send>;
7
8/// Resolve is a callback used to resolve an effect request and continue
9/// one of the capability Tasks running on the executor.
10pub enum RequestHandle<Out> {
11    Never,
12    Once(ResolveOnce<Out>),
13    Many(ResolveMany<Out>),
14}
15// ANCHOR_END: resolve
16
17pub trait Resolvable<Output> {
18    /// Resolve the request with the given output.
19    /// # Errors
20    /// Returns an error if the request is not expected to be resolved.
21    fn resolve(&mut self, output: Output) -> Result<(), ResolveError>;
22}
23
24impl<Output> Resolvable<Output> for RequestHandle<Output> {
25    fn resolve(&mut self, output: Output) -> Result<(), ResolveError> {
26        self.resolve(output)
27    }
28}
29
30impl<Output> RequestHandle<Output> {
31    /// Resolve the request with the given output.
32    /// # Errors
33    /// Returns an error if the request is not expected to be resolved.
34    pub fn resolve(&mut self, output: Output) -> Result<(), ResolveError> {
35        match self {
36            Self::Never => Err(ResolveError::Never),
37            Self::Many(f) => f(output).map_err(|()| ResolveError::FinishedMany),
38            Self::Once(_) => {
39                // The resolve has been used, turn it into a Never
40                if let Self::Once(f) = std::mem::replace(self, Self::Never) {
41                    f(output);
42                }
43
44                Ok(())
45            }
46        }
47    }
48}
49
50#[derive(Error, Debug)]
51pub enum ResolveError {
52    #[error("Attempted to resolve a request that is not expected to be resolved.")]
53    Never,
54    #[error("Attempted to resolve a request that has concluded.")]
55    FinishedMany,
56    #[error("Request with id {0} not found.")]
57    NotFound(u64),
58}