Reputation: 41
Class EvaluationStep
should holds dyn Eval<Context>
to be evaluated later.
To have simple test for each class, flexibility, easy moving and mixing steps such classes should:
eval
should use &mut self
, step classes has mutable stateIn general it should looks like:
let result = StepN::new(
// any number of steps in any order...
StepSecond::new(
StepFirst::new(initial)
)
).eval().await
Implementation example
use std::{future::Future, pin::Pin};
///
/// Async trait defined
pub trait Eval<'a, Out> {
fn eval(&'a mut self) -> Pin<Box<dyn Future<Output = Out> + 'a>>;
}
///
/// The Context to be returned from `Eval`
#[derive(Debug, Clone)]
pub struct Context {
result: f64,
}
///
/// Some struct implements async trai `Eval`
pub struct EvaluationStep<'a> {
ctx: Box<dyn Eval<'a, Context> + Send + 'a>,
}
impl<'a> EvaluationStep<'a> {
///
/// New instance [UserHook]
/// - `ctx` - [Eval]
pub fn new(ctx: impl Eval<'a, Context> + Send + 'a) -> Self {
Self { ctx: Box::new(ctx) }
}
}
impl<'a> Eval<'a, Context> for EvaluationStep<'a> {
fn eval(&'a mut self) -> Pin<Box<dyn Future<Output = Context> +'a>> {
Box::pin(async {
let mut ctx = self.ctx.eval().await;
ctx.result = 11.1;
ctx
})
}
}
///
/// Fake implements async trai `Eval`
pub struct FakeStep {
pub ctx: Context,
}
impl<'a> Eval<'a, Context> for FakeStep {
fn eval(&'a mut self) -> Pin<Box<dyn Future<Output = Context> +'a>> {
Box::pin(async {
self.ctx.clone()
})
}
}
//
//
#[tokio::main]
async fn main() {
std::env::set_var("RUST_LOG", "info");
env_logger::init();
let mut step = EvaluationStep::new(
FakeStep { ctx: Context { result: 0.0 } }
);
let result = step.eval().await;
log::info!("Result: {:?}", result);
}
Problem
error[E0597]: `step` does not live long enough
--> tokio_channel/src/async_trait/main.rs:57:18
|
54 | let mut step = EvaluationStep::new(
| -------- binding `step` declared here
...
57 | let result = step.eval().await;
| ^^^^ borrowed value does not live long enough
58 | log::info!("Result: {:?}", result);
59 | }
| -
| |
| `step` dropped here while still borrowed
| borrow might be used here, when `step` is dropped and runs the destructor for type `EvaluationStep<'_>`
With single lifetime playground
Upvotes: 0
Views: 38