1use std::path::Path;
4
5use anyhow::anyhow;
6use tokio_util::sync::CancellationToken;
7use wdl_analysis::Document;
8use wdl_engine::EvaluatedTask;
9use wdl_engine::EvaluationError;
10use wdl_engine::EvaluationResult;
11use wdl_engine::Events;
12use wdl_engine::Inputs;
13use wdl_engine::Outputs;
14use wdl_engine::config::Config;
15use wdl_engine::v1::TaskEvaluator;
16use wdl_engine::v1::WorkflowEvaluator;
17
18use crate::inputs::OriginPaths;
19
20pub struct Evaluator<'a> {
22 document: &'a Document,
24
25 name: &'a str,
27
28 inputs: Inputs,
30
31 origins: OriginPaths,
33
34 config: Config,
36
37 output_dir: &'a Path,
39}
40
41impl<'a> Evaluator<'a> {
42 pub fn new(
44 document: &'a Document,
45 name: &'a str,
46 inputs: Inputs,
47 origins: OriginPaths,
48 config: Config,
49 output_dir: &'a Path,
50 ) -> Self {
51 Self {
52 document,
53 name,
54 inputs,
55 origins,
56 config,
57 output_dir,
58 }
59 }
60
61 pub async fn run(
63 mut self,
64 token: CancellationToken,
65 events: Events,
66 ) -> EvaluationResult<Outputs> {
67 match self.inputs {
68 Inputs::Task(ref mut inputs) => {
69 let task = self.document.task_by_name(self.name).ok_or_else(|| {
70 anyhow!(
71 "document does not contain a task named `{name}`",
72 name = self.name
73 )
74 })?;
75
76 inputs
79 .join_paths(task, |key| {
80 self.origins
81 .get(key)
82 .ok_or(anyhow!("unable to find origin path for key `{key}`"))
83 })
84 .await?;
85
86 let evaluator = TaskEvaluator::new(self.config, token, events).await?;
87
88 evaluator
89 .evaluate(self.document, task, inputs, self.output_dir)
90 .await
91 .and_then(EvaluatedTask::into_result)
92 }
93 Inputs::Workflow(mut inputs) => {
94 let workflow = self
95 .document
96 .workflow()
97 .ok_or_else(|| anyhow!("document does not contain a workflow"))?;
98
99 if workflow.name() != self.name {
100 return Err(EvaluationError::Other(anyhow!(
101 "document does not contain a workflow named `{name}`",
102 name = self.name
103 )));
104 }
105
106 inputs
109 .join_paths(workflow, |key| {
110 self.origins
111 .get(key)
112 .ok_or(anyhow!("unable to find origin path for key `{key}`"))
113 })
114 .await?;
115
116 let evaluator = WorkflowEvaluator::new(self.config, token, events).await?;
117 evaluator
118 .evaluate(self.document, inputs, self.output_dir)
119 .await
120 }
121 }
122 }
123}