11use crate :: { CrossToml , Result , Target , TargetList } ;
22
3- use crate :: errors:: * ;
43use std:: collections:: HashMap ;
54use std:: env;
5+ use std:: str:: FromStr ;
66
77#[ derive( Debug ) ]
88struct Environment ( & ' static str , Option < HashMap < & ' static str , & ' static str > > ) ;
@@ -23,6 +23,19 @@ impl Environment {
2323 . or_else ( || env:: var ( name) . ok ( ) )
2424 }
2525
26+ fn get_values_for < T > (
27+ & self ,
28+ var : & str ,
29+ target : & Target ,
30+ convert : impl Fn ( & str ) -> T ,
31+ ) -> ( Option < T > , Option < T > ) {
32+ let target_values = self . get_target_var ( target, var) . map ( |ref s| convert ( s) ) ;
33+
34+ let build_values = self . get_build_var ( var) . map ( |ref s| convert ( s) ) ;
35+
36+ ( build_values, target_values)
37+ }
38+
2639 fn target_path ( target : & Target , key : & str ) -> String {
2740 format ! ( "TARGET_{target}_{key}" )
2841 }
@@ -39,27 +52,8 @@ impl Environment {
3952 self . get_var ( & self . build_var_name ( & Self :: target_path ( target, key) ) )
4053 }
4154
42- fn xargo ( & self , target : & Target ) -> Result < ( Option < bool > , Option < bool > ) > {
43- let ( build_xargo, target_xargo) = (
44- self . get_build_var ( "XARGO" ) ,
45- self . get_target_var ( target, "XARGO" ) ,
46- ) ;
47- let build_env = if let Some ( value) = build_xargo {
48- Some ( value. parse :: < bool > ( ) . wrap_err_with ( || {
49- format ! ( "error parsing {value} from XARGO environment variable" )
50- } ) ?)
51- } else {
52- None
53- } ;
54- let target_env = if let Some ( value) = target_xargo {
55- Some ( value. parse :: < bool > ( ) . wrap_err_with ( || {
56- format ! ( "error parsing {} from XARGO environment variable" , value)
57- } ) ?)
58- } else {
59- None
60- } ;
61-
62- Ok ( ( build_env, target_env) )
55+ fn xargo ( & self , target : & Target ) -> ( Option < bool > , Option < bool > ) {
56+ self . get_values_for ( "XARGO" , target, bool_from_envvar)
6357 }
6458
6559 fn image ( & self , target : & Target ) -> Option < String > {
@@ -71,38 +65,32 @@ impl Environment {
7165 }
7266
7367 fn passthrough ( & self , target : & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) {
74- self . get_values_for ( "ENV_PASSTHROUGH" , target)
68+ self . get_values_for ( "ENV_PASSTHROUGH" , target, split_to_cloned_by_ws )
7569 }
7670
7771 fn volumes ( & self , target : & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) {
78- self . get_values_for ( "ENV_VOLUMES" , target)
72+ self . get_values_for ( "ENV_VOLUMES" , target, split_to_cloned_by_ws )
7973 }
8074
8175 fn target ( & self ) -> Option < String > {
8276 self . get_build_var ( "TARGET" )
8377 }
84-
85- fn get_values_for (
86- & self ,
87- var : & str ,
88- target : & Target ,
89- ) -> ( Option < Vec < String > > , Option < Vec < String > > ) {
90- let target_values = self
91- . get_target_var ( target, var)
92- . map ( |ref s| split_to_cloned_by_ws ( s) ) ;
93-
94- let build_values = self
95- . get_build_var ( var)
96- . map ( |ref s| split_to_cloned_by_ws ( s) ) ;
97-
98- ( build_values, target_values)
99- }
10078}
10179
10280fn split_to_cloned_by_ws ( string : & str ) -> Vec < String > {
10381 string. split_whitespace ( ) . map ( String :: from) . collect ( )
10482}
10583
84+ pub fn bool_from_envvar ( envvar : & str ) -> bool {
85+ if let Ok ( value) = bool:: from_str ( envvar) {
86+ value
87+ } else if let Ok ( value) = i32:: from_str ( envvar) {
88+ value != 0
89+ } else {
90+ !envvar. is_empty ( )
91+ }
92+ }
93+
10694#[ derive( Debug ) ]
10795pub struct Config {
10896 toml : Option < CrossToml > ,
@@ -136,72 +124,97 @@ impl Config {
136124 }
137125 }
138126
139- # [ cfg ( test ) ]
140- fn new_with ( toml : Option < CrossToml > , env : Environment ) -> Self {
141- Config { toml , env }
142- }
143-
144- pub fn xargo ( & self , target : & Target ) -> Result < Option < bool > > {
145- let ( build_xargo , target_xargo ) = self . env . xargo ( target) ? ;
146- let ( toml_build_xargo , toml_target_xargo ) = if let Some ( ref toml) = self . toml {
147- toml . xargo ( target)
127+ fn bool_from_config (
128+ & self ,
129+ target : & Target ,
130+ env : impl Fn ( & Environment , & Target ) -> ( Option < bool > , Option < bool > ) ,
131+ config : impl Fn ( & CrossToml , & Target ) -> ( Option < bool > , Option < bool > ) ,
132+ ) -> Option < bool > {
133+ let ( env_build , env_target ) = env ( & self . env , target) ;
134+ let ( toml_build , toml_target ) = if let Some ( ref toml) = self . toml {
135+ config ( toml , target)
148136 } else {
149137 ( None , None )
150138 } ;
151139
152- match ( build_xargo , toml_build_xargo ) {
153- ( xargo @ Some ( _ ) , _) => return Ok ( xargo ) ,
154- ( None , xargo @ Some ( _ ) ) => return Ok ( xargo ) ,
140+ match ( env_build , toml_build ) {
141+ ( Some ( value ) , _) => return Some ( value ) ,
142+ ( None , Some ( value ) ) => return Some ( value ) ,
155143 ( None , None ) => { }
156144 } ;
157145
158- match ( target_xargo , toml_target_xargo ) {
159- ( xargo @ Some ( _ ) , _) => return Ok ( xargo ) ,
160- ( None , xargo @ Some ( _ ) ) => return Ok ( xargo ) ,
146+ match ( env_target , toml_target ) {
147+ ( Some ( value ) , _) => return Some ( value ) ,
148+ ( None , Some ( value ) ) => return Some ( value ) ,
161149 ( None , None ) => { }
162150 } ;
163- Ok ( None )
164- }
165151
166- pub fn image ( & self , target : & Target ) -> Result < Option < String > > {
167- let env_value = self . env . image ( target) ;
168- if let Some ( env_value) = env_value {
169- return Ok ( Some ( env_value) ) ;
170- }
171- self . toml . as_ref ( ) . map_or ( Ok ( None ) , |t| Ok ( t. image ( target) ) )
152+ None
172153 }
173154
174- pub fn runner ( & self , target : & Target ) -> Result < Option < String > > {
175- let env_value = self . env . runner ( target) ;
155+ fn string_from_config (
156+ & self ,
157+ target : & Target ,
158+ env : impl Fn ( & Environment , & Target ) -> Option < String > ,
159+ config : impl Fn ( & CrossToml , & Target ) -> Option < String > ,
160+ ) -> Result < Option < String > > {
161+ let env_value = env ( & self . env , target) ;
176162 if let Some ( env_value) = env_value {
177163 return Ok ( Some ( env_value) ) ;
178164 }
179165 self . toml
180166 . as_ref ( )
181- . map_or ( Ok ( None ) , |t| Ok ( t . runner ( target) ) )
167+ . map_or ( Ok ( None ) , |t| Ok ( config ( t , target) ) )
182168 }
183169
184- pub fn env_passthrough ( & self , target : & Target ) -> Result < Vec < String > > {
185- let ( env_build, env_target) = self . env . passthrough ( target) ;
186-
187- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t. env_passthrough_build ( ) ) ;
188- let mut collected = Self :: sum_of_env_toml_values ( toml_getter, env_build) ?;
170+ fn vec_from_config (
171+ & self ,
172+ target : & Target ,
173+ env : impl Fn ( & Environment , & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) ,
174+ config_build : impl for < ' a > Fn ( & ' a CrossToml ) -> & ' a [ String ] ,
175+ config_target : impl for < ' a > Fn ( & ' a CrossToml , & Target ) -> & ' a [ String ] ,
176+ ) -> Result < Vec < String > > {
177+ let ( env_build, env_target) = env ( & self . env , target) ;
189178
190- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t . env_passthrough_target ( target ) ) ;
191- collected. extend ( Self :: sum_of_env_toml_values ( toml_getter , env_target ) ?) ;
179+ let mut collected = self . sum_of_env_toml_values ( env_build , config_build ) ? ;
180+ collected. extend ( self . sum_of_env_toml_values ( env_target , |t| config_target ( t , target ) ) ?) ;
192181
193182 Ok ( collected)
194183 }
195184
196- pub fn env_volumes ( & self , target : & Target ) -> Result < Vec < String > > {
197- let ( env_build , env_target ) = self . env . volumes ( target ) ;
198- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t . env_volumes_build ( ) ) ;
199- let mut collected = Self :: sum_of_env_toml_values ( toml_getter , env_build ) ? ;
185+ # [ cfg ( test ) ]
186+ fn new_with ( toml : Option < CrossToml > , env : Environment ) -> Self {
187+ Config { toml, env }
188+ }
200189
201- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t. env_volumes_target ( target) ) ;
202- collected. extend ( Self :: sum_of_env_toml_values ( toml_getter, env_target) ?) ;
190+ pub fn xargo ( & self , target : & Target ) -> Option < bool > {
191+ self . bool_from_config ( target, Environment :: xargo, CrossToml :: xargo)
192+ }
203193
204- Ok ( collected)
194+ pub fn image ( & self , target : & Target ) -> Result < Option < String > > {
195+ self . string_from_config ( target, Environment :: image, CrossToml :: image)
196+ }
197+
198+ pub fn runner ( & self , target : & Target ) -> Result < Option < String > > {
199+ self . string_from_config ( target, Environment :: runner, CrossToml :: runner)
200+ }
201+
202+ pub fn env_passthrough ( & self , target : & Target ) -> Result < Vec < String > > {
203+ self . vec_from_config (
204+ target,
205+ Environment :: passthrough,
206+ CrossToml :: env_passthrough_build,
207+ CrossToml :: env_passthrough_target,
208+ )
209+ }
210+
211+ pub fn env_volumes ( & self , target : & Target ) -> Result < Vec < String > > {
212+ self . vec_from_config (
213+ target,
214+ Environment :: volumes,
215+ CrossToml :: env_volumes_build,
216+ CrossToml :: env_volumes_target,
217+ )
205218 }
206219
207220 pub fn target ( & self , target_list : & TargetList ) -> Option < Target > {
@@ -213,15 +226,16 @@ impl Config {
213226 . and_then ( |t| t. default_target ( target_list) )
214227 }
215228
216- fn sum_of_env_toml_values (
217- toml_getter : impl FnOnce ( ) -> Option < Vec < String > > ,
229+ fn sum_of_env_toml_values < ' a > (
230+ & ' a self ,
218231 env_values : Option < Vec < String > > ,
232+ toml_getter : impl FnOnce ( & ' a CrossToml ) -> & ' a [ String ] ,
219233 ) -> Result < Vec < String > > {
220234 let mut collect = vec ! [ ] ;
221235 if let Some ( mut vars) = env_values {
222236 collect. append ( & mut vars) ;
223- } else if let Some ( toml_values) = toml_getter ( ) {
224- collect. extend ( toml_values. into_iter ( ) ) ;
237+ } else if let Some ( toml_values) = self . toml . as_ref ( ) . map ( toml_getter ) {
238+ collect. extend ( toml_values. iter ( ) . cloned ( ) ) ;
225239 }
226240
227241 Ok ( collect)
@@ -231,6 +245,7 @@ impl Config {
231245#[ cfg( test) ]
232246mod tests {
233247 use super :: * ;
248+ use crate :: errors:: * ;
234249 use crate :: { Target , TargetList } ;
235250
236251 fn target_list ( ) -> TargetList {
@@ -257,24 +272,17 @@ mod tests {
257272 map. insert ( "CROSS_BUILD_XARGO" , "tru" ) ;
258273
259274 let env = Environment :: new ( Some ( map) ) ;
260-
261- let res = env. xargo ( & target ( ) ) ;
262- if res. is_ok ( ) {
263- panic ! ( "invalid bool string parsing should fail" ) ;
264- }
275+ assert_eq ! ( env. xargo( & target( ) ) , ( Some ( true ) , None ) ) ;
265276 }
266277
267278 #[ test]
268- pub fn build_and_target_set_returns_tuple ( ) -> Result < ( ) > {
279+ pub fn build_and_target_set_returns_tuple ( ) {
269280 let mut map = std:: collections:: HashMap :: new ( ) ;
270281 map. insert ( "CROSS_BUILD_XARGO" , "true" ) ;
271282 map. insert ( "CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO" , "false" ) ;
272283
273284 let env = Environment :: new ( Some ( map) ) ;
274-
275- assert_eq ! ( env. xargo( & target( ) ) ?, ( Some ( true ) , Some ( false ) ) ) ;
276-
277- Ok ( ( ) )
285+ assert_eq ! ( env. xargo( & target( ) ) , ( Some ( true ) , Some ( false ) ) ) ;
278286 }
279287
280288 #[ test]
@@ -329,7 +337,7 @@ mod tests {
329337
330338 let env = Environment :: new ( Some ( map) ) ;
331339 let config = Config :: new_with ( Some ( toml ( TOML_BUILD_XARGO_FALSE ) ?) , env) ;
332- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( true ) ) ) ) ;
340+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
333341
334342 Ok ( ( ) )
335343 }
@@ -341,7 +349,7 @@ mod tests {
341349 let env = Environment :: new ( Some ( map) ) ;
342350
343351 let config = Config :: new_with ( Some ( toml ( TOML_TARGET_XARGO_FALSE ) ?) , env) ;
344- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( true ) ) ) ) ;
352+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
345353
346354 Ok ( ( ) )
347355 }
@@ -352,7 +360,7 @@ mod tests {
352360 map. insert ( "CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO" , "true" ) ;
353361 let env = Environment :: new ( Some ( map) ) ;
354362 let config = Config :: new_with ( Some ( toml ( TOML_BUILD_XARGO_FALSE ) ?) , env) ;
355- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( false ) ) ) ) ;
363+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( false ) ) ) ;
356364
357365 Ok ( ( ) )
358366 }
0 commit comments