1#[cfg(test)]
2mod test;
3
4use dto::Response;
5use util;
6
7#[derive( Debug, PartialEq)]
8pub struct Work {
9 instruction: Instruction,
10 error: Option<Instruction>
11}
12
13impl Work {
14 pub fn instruction(instruction: Instruction) -> Work {
15 Work { instruction, error: None }
16 }
17 pub fn response(response: Response) -> Work {
18 Work { instruction: Instruction::ExitCode(response), error: None }
19 }
20 pub fn on_error(self, instruction: Instruction) -> Work {
21 Work { error: Some(instruction), ..self }
22 }
23
24 fn run(self, runner: &InstructionRunner) -> Response {
25 match runner.run(&self.instruction) {
26 Response::Err(error) => {
27 self.error
28 .map(|a| runner.run(&a))
29 .unwrap_or(Response::Err(error))
30 },
31 r => r
32 }
33 }
34}
35
36#[derive( Debug, PartialEq, Clone)]
37pub enum Instruction {
38 Display(String, Response),
39 SystemCommand(String, bool),
40 ExitCode(Response)
41}
42
43pub trait InstructionRunner {
44 fn run(&self, instruction: &Instruction) -> Response;
45}
46
47pub struct SystemRunner;
48impl InstructionRunner for SystemRunner {
49 fn run(&self, instruction: &Instruction) -> Response {
50 match *instruction {
51 Instruction::Display(ref string, ref response) => {
52 println!("{}", string);
53 response.clone()
54 },
55 Instruction::SystemCommand(ref shell, output) => util::run_system_command(shell, output),
56 Instruction::ExitCode(ref response) => response.clone()
57 }
58 }
59}
60
61pub fn run_workflow(workflow: Vec<Work>, runner: &InstructionRunner) -> Response {
62 let mut response = Response::Ok;
63 'work: for work in workflow {
64 response = work.run(runner);
65 if let Response::Err(_) = response {
66 break 'work;
67 }
68 }
69 response
70}