1 个不稳定版本

0.1.0 2022 年 4 月 24 日

#25#constructing


用于 libmw

MIT 许可证

3KB

构建中间件函数管道的库,允许在返回上一个函数调用之前,如果需要,可以调用链中的下一个函数。

这允许程序员在调用链中的下一个函数之前和之后,对给定上下文执行工作。

示例

use libmw::prelude::*;

/// Sample free standing handler function
fn standalone_func(ctx: &mut dyn PipelineContext, next: Pipeline) -> Result<(), PipelineError> {
  // do work before calling the next handler in the pipe
  println!("before in handler func");
  next.invoke(ctx)?;

  // do work after the next handler in the pipe returns
  println!("after in handler func");
  
  Ok(())
}

/// Use free standing functions to add additional trait bounds your context implements
/// for generic handlers that can be shared without needing knowledge of the implemented `PipelineContext`
fn standalone_func_enhance<CtxType>(ctx: &mut dyn PipelineContext, next: Pipeline) -> Result<(), PipelineError> 
where:
  CtxType: PipelineContext + Repeatable + 'static {
  if let Some(context) = ctx.as_any_mut().downcast_mut::<CtxType>() {
		while context.repeat() {
			next.invoke(context)?;

			if context.delay() != 0 {
				std::thread::sleep(std::time::Duration::from_millis(context.delay() as u64));
			}
		}
	}
  
  Ok(())
}

#[derive(PipelineContext)]
struct Context {
  take_branch: bool
}

fn main() {
  let mut builder = PipelineBuilder::new();

  // add freestanding function
  builder.with(standalone_func);

  // branch taken depending on how context was created
  builder.when(
    |ctx| match ctx.as_any().downcast_ref::<Context>() {
      Some(c) => c.take_branch,
      None => false,
    },
    |builder| {
      builder.with(|ctx, next| {
        println!("branch handler 1 before");
        next.invoke(ctx)?;
        println!("branch handler 1 after");

        Ok(())
      });

      builder.with(|ctx, next| {
        println!("branch handler 2 before");
        next.invoke(ctx)?;
        println!("branch handler 2 after");

        Ok(())
      });
    },
  );

  // with closure
  builder.with(|ctx, next| {
    // do work before calling the next handler in the pipe
  	println!("before in closure");
  	next.invoke(ctx)?;

    // do work after the next handler in the pipe returns
  	println!("after in closure");

  	Ok(())
  });
  
  // assemble the pipeline
  let pipeline = builder.assemble();

  // create context and call pipeline
  let mut context = Context { take_branch: true };
  let result = pipeline.invoke(&mut context);
  match result {
    Ok(_) -> {
      // deal with your mutated context
    }
    Err(_) => {
      // handle your pipeline errors
    }
  }
}

依赖项

~1.5MB
~35K SLoC