Storing async fns as struct members

I'm trying to have a struct with a collection of "function pointers". I'd like to populate this structure and later on call individual functions. Something like this (stripped down version):

struct Services {
    s1: Fn(String) -> futures::Future<Output = Option<String>>,
    // s2: Fn(...) -> Future<...>,
    // s3: Fn(...) -> Future<...>,
}

async fn main_test(input: String) {
    let s = Services { s1: dummy_s1 };

    (s.s1)(input).await.unwrap();
}

async fn dummy_s1(input: String) -> Option<String> {
    Some(input)
}

It's missing some dyns and Boxes but perhaps I have been trying to overcomplicate things. What is the most "natural" way of implementing this?

You may find this thread useful.

1 Like

Thank you, I was so close but it's so difficult to tell when you don't know what you're doing. :slight_smile:

The missing link was the function/closure returning Box::pin. I should've guessed it since I already have code that does something very similar when spawning recursive tasks. What's completely new to me is the fn(..) -> .. bit, I thought I needed Fn/FnMut/FnOnce trait.

Here's a working version:

struct Services {
    s1: fn(String) -> Pin<Box<dyn Future<Output = Option<String>>>>,
}

pub async fn main_test(input: String) {
    let s = Services {
        s1: |input| Box::pin(dummy_s1(input)),
    };

    (s.s1)(input).await.unwrap();
}

async fn dummy_s1(input: String) -> Option<String> {
    Some(input)
}

Version with BoxFuture which makes it rather straightforward to work with borrowed values:

struct Services {
    s1: for <'a> fn(&'a str) -> BoxFuture<'a, Option<String>>,
}

pub async fn main_test(input: &str) {
    let s = Services {
        s1: |input| Box::pin(dummy_s1(input)),
    };

    (s.s1)(input).await.unwrap();
}

async fn dummy_s1(input: &str) -> Option<String> {
    Some(input.to_owned())
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.