使用异步闭包作为 HRTB 的 lambda 函数

问题描述 投票:0回答:0

我正在尝试使用异步闭包作为 lambda 函数(在其他语言中非常典型)。

但是我才发现还有更破的东西我不明白:

回复:https://www.rustexplorer.com/b/w6fmvw.

错误:

error: lifetime may not live long enough
   --> src/main.rs:101:17
    |
94  |       async fn handle(&self, input: &PlayerChangeNameInput, whoami: &str) -> Result<Player, ()> {
    |                                     - lifetime `'life1` defined here
...
101 | /                 Box::pin(async {
102 | |                     let o = Player {
103 | |                         id: musts.actual.id.clone(),
104 | |                         name: input.name.to_string(),
...   |
107 | |                     Ok(o)
108 | |                 })
    | |__________________^ returning this value requires that `'life1` must outlive `'static`

代码:

/*
[dependencies]
async-trait = { version = "0.1.68" }
tokio = { version = "1.26.0", features = ["macros", "rt-multi-thread"] }
*/

use std::{future::Future, pin::Pin, sync::Arc};

trait Trait: Send + Sync + PlayerTrait {}

impl<T: PlayerTrait> Trait for T {}

#[async_trait::async_trait]
trait PlayerTrait: Send + Sync {
    async fn player_change_name(
        &self,
        input: &PlayerChangeNameInput,
        lambda: &(dyn for<'a> Fn(
            PlayerMusts<'a>,
        ) -> Pin<Box<dyn Future<Output = Result<Player, ()>> + Send + 'a>>
              + Sync),
    ) -> Result<Player, ()>;
}

struct PlayerChangeNameInput {
    pub name: String,
}

struct Player {
    pub id: String,
    pub name: String,
}

struct PlayerMusts<'a> {
    pub actual: &'a Player,
    // pub other: &'a str,
}

#[async_trait::async_trait]
impl PlayerTrait for Repo {
    async fn player_change_name(
        &self,
        input: &PlayerChangeNameInput,
        lambda: &(dyn for<'a> Fn(
            PlayerMusts<'a>,
        ) -> Pin<Box<dyn Future<Output = Result<Player, ()>> + Send + 'a>>
              + Sync),
    ) -> Result<Player, ()> {
        // I need input here
        dbg!(&input.name);

        // I need to await for many things in here

        // Eg. for DB connection pool...
        // let mut db_connection = pool.begin().await?;

        // Here I can query the actual player, I'm faking it now...
        let actual = Player {
            id: "1".to_string(),
            name: "Bob".to_string(),
        };

        let worked_player = lambda(PlayerMusts {
            actual: &actual,
            // other: "Other",
        })
        .await?;

        // I'm saving the lambda result here, I'm faking it now...
        // let result = db_connection.save(&worked_player, &actual).await?;
        let result = worked_player;

        // db_connection.save_and_close().await?;

        Ok(result)
    }
}

struct HandlerImpl {
    repo: Arc<Repo>,
}

fn new_handler(repo: Arc<Repo>) -> Box<dyn Handler> {
    Box::new(HandlerImpl { repo })
}

#[async_trait::async_trait]
trait Handler: Send + Sync {
    async fn handle(&self, input: &PlayerChangeNameInput, whoami: &str) -> Result<Player, ()>;
}

#[async_trait::async_trait]
impl Handler for HandlerImpl {
    async fn handle(&self, input: &PlayerChangeNameInput, whoami: &str) -> Result<Player, ()> {
        // use whoami here...
        dbg!(whoami);

        let result = self
            .repo
            .player_change_name(input, &|musts| {
                Box::pin(async {
                    let o = Player {
                        id: musts.actual.id.clone(),
                        name: input.name.to_string(),
                    };

                    Ok(o)
                })
            })
            .await?;

        Ok(result)
    }
}

pub struct Repo {
    // pub pool: Arc<DbPool>,
}

impl Repo {
    pub fn new() -> Self {
        Self {}
    }
}

#[tokio::main]
async fn main() -> Result<(), ()> {
    let db_repo = Arc::new(Repo::new());

    let handler = new_handler(db_repo);

    let whoami = "Myself";

    let fake_input = &PlayerChangeNameInput{name: "Frank".to_string()};

    let result = handler.handle(fake_input, whoami).await?;

    dbg!(result.name);

    Ok(())
}
rust lambda closures hrtb
© www.soinside.com 2019 - 2024. All rights reserved.