@@ -6,38 +6,43 @@ pub mod staging;
66pub mod util;
77pub mod validate;
88
9+ use cwl:: requirements:: { FromRequirement , Requirement } ;
910use cwl:: types:: { guess_type, CWLType , DefaultValue , Directory , File , PathItem } ;
1011use cwl:: CWLDocument ;
1112use io:: preprocess_path_join;
1213use runner:: { run_tool, run_workflow} ;
14+ use serde:: { Deserialize , Serialize } ;
1315use serde_yaml:: Value ;
1416use std:: { cell:: RefCell , collections:: HashMap , error:: Error , fmt:: Display , fs, num:: NonZero , path:: Path , process:: Command , thread} ;
1517use sysinfo:: { Disks , MemoryRefreshKind , System } ;
1618use util:: preprocess_cwl;
1719
1820pub fn execute_cwlfile ( cwlfile : impl AsRef < Path > , raw_inputs : & [ String ] , outdir : Option < impl AsRef < Path > > ) -> Result < ( ) , Box < dyn Error > > {
1921 //gather inputs
20- let mut inputs = if raw_inputs. len ( ) == 1 && !raw_inputs[ 0 ] . starts_with ( '-' ) {
22+ let mut input_values = if raw_inputs. len ( ) == 1 && !raw_inputs[ 0 ] . starts_with ( '-' ) {
2123 let yaml = fs:: read_to_string ( & raw_inputs[ 0 ] ) ?;
2224 serde_yaml:: from_str ( & yaml) . map_err ( |e| format ! ( "Could not read job file: {e}" ) ) ?
2325 } else {
24- raw_inputs
25- . chunks_exact ( 2 )
26- . filter_map ( |pair| {
27- if let Some ( key) = pair[ 0 ] . strip_prefix ( "--" ) {
28- let raw_value = & pair[ 1 ] ;
29- let value = match guess_type ( raw_value) {
30- CWLType :: File => DefaultValue :: File ( File :: from_location ( raw_value) ) ,
31- CWLType :: Directory => DefaultValue :: Directory ( Directory :: from_location ( raw_value) ) ,
32- CWLType :: String => DefaultValue :: Any ( Value :: String ( raw_value. to_string ( ) ) ) ,
33- _ => DefaultValue :: Any ( serde_yaml:: from_str ( raw_value) . expect ( "Could not read input" ) ) ,
34- } ;
35- Some ( ( key. to_string ( ) , value) )
36- } else {
37- None
38- }
39- } )
40- . collect :: < HashMap < _ , _ > > ( )
26+ InputObject {
27+ inputs : raw_inputs
28+ . chunks_exact ( 2 )
29+ . filter_map ( |pair| {
30+ if let Some ( key) = pair[ 0 ] . strip_prefix ( "--" ) {
31+ let raw_value = & pair[ 1 ] ;
32+ let value = match guess_type ( raw_value) {
33+ CWLType :: File => DefaultValue :: File ( File :: from_location ( raw_value) ) ,
34+ CWLType :: Directory => DefaultValue :: Directory ( Directory :: from_location ( raw_value) ) ,
35+ CWLType :: String => DefaultValue :: Any ( Value :: String ( raw_value. to_string ( ) ) ) ,
36+ _ => DefaultValue :: Any ( serde_yaml:: from_str ( raw_value) . expect ( "Could not read input" ) ) ,
37+ } ;
38+ Some ( ( key. to_string ( ) , value) )
39+ } else {
40+ None
41+ }
42+ } )
43+ . collect :: < HashMap < _ , _ > > ( ) ,
44+ ..Default :: default ( )
45+ }
4146 } ;
4247
4348 fn correct_path < T : PathItem > ( item : & mut T , path_prefix : & Path ) {
@@ -69,15 +74,15 @@ pub fn execute_cwlfile(cwlfile: impl AsRef<Path>, raw_inputs: &[String], outdir:
6974 } else {
7075 Path :: new ( "." )
7176 } ;
72- for value in inputs. values_mut ( ) {
77+ for value in input_values . inputs . values_mut ( ) {
7378 match value {
7479 DefaultValue :: File ( file) => correct_path ( file, path_prefix) ,
7580 DefaultValue :: Directory ( directory) => correct_path ( directory, path_prefix) ,
7681 _ => ( ) ,
7782 }
7883 }
7984
80- let output_values = execute ( cwlfile, inputs , outdir, None ) ?;
85+ let output_values = execute ( cwlfile, input_values , outdir, None ) ?;
8186 let json = serde_json:: to_string_pretty ( & output_values) ?;
8287 println ! ( "{json}" ) ;
8388
@@ -86,7 +91,7 @@ pub fn execute_cwlfile(cwlfile: impl AsRef<Path>, raw_inputs: &[String], outdir:
8691
8792pub fn execute (
8893 cwlfile : impl AsRef < Path > ,
89- inputs : HashMap < String , DefaultValue > ,
94+ input_values : InputObject ,
9095 outdir : Option < impl AsRef < Path > > ,
9196 cwl_doc : Option < & CWLDocument > ,
9297) -> Result < HashMap < String , DefaultValue > , Box < dyn Error > > {
@@ -102,19 +107,67 @@ pub fn execute(
102107 match doc {
103108 CWLDocument :: CommandLineTool ( _) | CWLDocument :: ExpressionTool ( _) => run_tool (
104109 & mut doc,
105- inputs ,
110+ input_values ,
106111 Some ( & cwlfile. as_ref ( ) . to_path_buf ( ) ) ,
107112 outdir. map ( |d| d. as_ref ( ) . to_string_lossy ( ) . into_owned ( ) ) ,
108113 ) ,
109114 CWLDocument :: Workflow ( mut workflow) => run_workflow (
110115 & mut workflow,
111- inputs ,
116+ input_values ,
112117 Some ( & cwlfile. as_ref ( ) . to_path_buf ( ) ) ,
113118 outdir. map ( |d| d. as_ref ( ) . to_string_lossy ( ) . into_owned ( ) ) ,
114119 ) ,
115120 }
116121}
117122
123+ #[ derive( Serialize , Deserialize , Debug , Default , PartialEq , Clone ) ]
124+ pub struct InputObject {
125+ #[ serde( flatten) ]
126+ pub inputs : HashMap < String , DefaultValue > ,
127+ #[ serde( rename = "cwl:requirements" ) ]
128+ #[ serde( default ) ]
129+ pub requirements : Vec < Requirement > ,
130+ #[ serde( rename = "cwl:hints" ) ]
131+ #[ serde( default ) ]
132+ pub hints : Vec < Requirement > ,
133+ }
134+
135+ impl InputObject {
136+ pub fn get_requirement < T > ( & self ) -> Option < & T >
137+ where
138+ Requirement : FromRequirement < T > ,
139+ {
140+ self . requirements . iter ( ) . chain ( self . hints . iter ( ) ) . find_map ( |req| Requirement :: get ( req) )
141+ }
142+
143+ pub fn add_requirement ( & mut self , requirement : & Requirement ) {
144+ if self
145+ . requirements
146+ . iter ( )
147+ . any ( |r| std:: mem:: discriminant ( r) == std:: mem:: discriminant ( requirement) )
148+ {
149+ return ;
150+ }
151+ self . requirements . push ( requirement. clone ( ) ) ;
152+ }
153+
154+ pub fn add_hint ( & mut self , hint : & Requirement ) {
155+ if self . hints . iter ( ) . any ( |r| std:: mem:: discriminant ( r) == std:: mem:: discriminant ( hint) ) {
156+ return ;
157+ }
158+ self . hints . push ( hint. clone ( ) ) ;
159+ }
160+ }
161+
162+ impl From < HashMap < String , DefaultValue > > for InputObject {
163+ fn from ( inputs : HashMap < String , DefaultValue > ) -> Self {
164+ Self {
165+ inputs,
166+ ..Default :: default ( )
167+ }
168+ }
169+ }
170+
118171pub trait ExitCode {
119172 fn exit_code ( & self ) -> i32 ;
120173}
0 commit comments