Skip to content

Instantly share code, notes, and snippets.

@jberkenbilt
Created December 1, 2024 00:51
Show Gist options
  • Save jberkenbilt/c8b0a0b6545b784acb91f2b262da8d89 to your computer and use it in GitHub Desktop.
Save jberkenbilt/c8b0a0b6545b784acb91f2b262da8d89 to your computer and use it in GitHub Desktop.
Go to Rust: 03 MethodCaller trait
trait MethodCaller<'a, ArgT, ResultT>: FnOnce(&'a Controller, ArgT) -> Self::Fut {
type Fut: Future<Output = Result<ResultT, Box<dyn Error + Sync + Send>>>;
}
impl<
'a,
ArgT,
ResultT,
FnT: FnOnce(&'a Controller, ArgT) -> Fut,
Fut: Future<Output = Result<ResultT, Box<dyn Error + Sync + Send>>>,
> MethodCaller<'a, ArgT, ResultT> for FnT
{
type Fut = Fut;
}
/// This is a generic dispatcher that is used by the wrapper API to
/// call methods on the singleton. It takes a closure that takes a
/// &[Controller] and an arg, calls the closure using the singleton,
/// and returns the result. The [MethodCaller] trait ties the lifetime
/// of the controller to the lifetime of the Future.
fn run_method<ArgT, ResultT, FnT>(
f: FnT,
arg: ArgT,
) -> Result<ResultT, Box<dyn Error + Sync + Send>>
where
for<'a> FnT: MethodCaller<'a, ArgT, ResultT>,
// Some day, one of these will work:
// FnT: async FnOnce(&Controller, ArgT) -> Result<ResultT, Box<dyn Error + Sync + Send>>,
// FnT: std::ops::AsyncFnOnce(&Controller, ArgT) -> Result<ResultT, Box<dyn Error + Sync + Send>>,
{
let lock = CONTROLLER.controller.read().unwrap();
let Some(controller) = &*lock else {
return Err("call init first".into());
};
CONTROLLER.rt.block_on(f(controller, arg))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment