Skip to main content

crux_core/core/
resolve.rs

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