For example, I use the deadpool-postgres crate for database pooling. Getting a connection looks like this:
let conn = self.pool.get().await?;
Because of RAII, you don't need a higher-order function helper, but if you really wanted to make one: async fn with_conn<T>(
&self,
f: impl AsyncFnOnce(Object<Manager>) -> Result<T>,
) -> Result<T> {
let conn = self.pool.get().await?;
f(conn).await
}
Now you can do: with_conn(|conn| async move {
conn.query("SELECT 1") // Or whatever
}).await
If you know TypeScript, this shouldn't be too difficult to read or write. The gnarliest stuff here is knowing the type signature of the function argument; because of async, it must be AsyncFnOnce, for one, and you need to know that the type that the deadpool crate returns is called Object<Manager> (which doesn't sound like a connection, to be fair). Determining the exact concrete type to match type constraints on is sometimes a chore, but TypeScript is surely no different here!If you don't know Rust too well, the "move" part will be a little mysterious, to be sure.