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 , Convert : Fn ( & str ) -> T > (
27+ & self ,
28+ var : & str ,
29+ target : & Target ,
30+ convert : Convert ,
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,113 @@ 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 < Env , Config > (
128+ & self ,
129+ target : & Target ,
130+ env : Env ,
131+ config : Config ,
132+ ) -> Option < bool >
133+ where
134+ Env : Fn ( & Environment , & Target ) -> ( Option < bool > , Option < bool > ) ,
135+ Config : Fn ( & CrossToml , & Target ) -> ( Option < bool > , Option < bool > ) ,
136+ {
137+ let ( env_build, env_target) = env ( & self . env , target) ;
138+ let ( toml_build, toml_target) = if let Some ( ref toml) = self . toml {
139+ config ( toml, target)
148140 } else {
149141 ( None , None )
150142 } ;
151143
152- match ( build_xargo , toml_build_xargo ) {
153- ( xargo @ Some ( _ ) , _) => return Ok ( xargo ) ,
154- ( None , xargo @ Some ( _ ) ) => return Ok ( xargo ) ,
144+ match ( env_build , toml_build ) {
145+ ( Some ( value ) , _) => return Some ( value ) ,
146+ ( None , Some ( value ) ) => return Some ( value ) ,
155147 ( None , None ) => { }
156148 } ;
157149
158- match ( target_xargo , toml_target_xargo ) {
159- ( xargo @ Some ( _ ) , _) => return Ok ( xargo ) ,
160- ( None , xargo @ Some ( _ ) ) => return Ok ( xargo ) ,
150+ match ( env_target , toml_target ) {
151+ ( Some ( value ) , _) => return Some ( value ) ,
152+ ( None , Some ( value ) ) => return Some ( value ) ,
161153 ( None , None ) => { }
162154 } ;
163- Ok ( None )
164- }
165155
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) ) )
156+ None
172157 }
173158
174- pub fn runner ( & self , target : & Target ) -> Result < Option < String > > {
175- let env_value = self . env . runner ( target) ;
159+ fn string_from_config < Env , Config > (
160+ & self ,
161+ target : & Target ,
162+ env : Env ,
163+ config : Config ,
164+ ) -> Result < Option < String > >
165+ where
166+ Env : Fn ( & Environment , & Target ) -> Option < String > ,
167+ Config : Fn ( & CrossToml , & Target ) -> Option < String > ,
168+ {
169+ let env_value = env ( & self . env , target) ;
176170 if let Some ( env_value) = env_value {
177171 return Ok ( Some ( env_value) ) ;
178172 }
179173 self . toml
180174 . as_ref ( )
181- . map_or ( Ok ( None ) , |t| Ok ( t . runner ( target) ) )
175+ . map_or ( Ok ( None ) , |t| Ok ( config ( t , target) ) )
182176 }
183177
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 ( ) ) ;
178+ fn vec_from_config < Env , ConfigBuild , ConfigTarget > (
179+ & self ,
180+ target : & Target ,
181+ env : Env ,
182+ config_build : ConfigBuild ,
183+ config_target : ConfigTarget ,
184+ ) -> Result < Vec < String > >
185+ where
186+ Env : Fn ( & Environment , & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) ,
187+ ConfigBuild : Fn ( & CrossToml ) -> Vec < String > ,
188+ ConfigTarget : Fn ( & CrossToml , & Target ) -> Vec < String > ,
189+ {
190+ let ( env_build, env_target) = env ( & self . env , target) ;
191+
192+ let toml_getter = || self . toml . as_ref ( ) . map ( config_build) ;
188193 let mut collected = Self :: sum_of_env_toml_values ( toml_getter, env_build) ?;
189194
190- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t . env_passthrough_target ( target) ) ;
195+ let toml_getter = || self . toml . as_ref ( ) . map ( |t| config_target ( t , target) ) ;
191196 collected. extend ( Self :: sum_of_env_toml_values ( toml_getter, env_target) ?) ;
192197
193198 Ok ( collected)
194199 }
195200
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 ) ? ;
201+ # [ cfg ( test ) ]
202+ fn new_with ( toml : Option < CrossToml > , env : Environment ) -> Self {
203+ Config { toml, env }
204+ }
200205
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) ?) ;
206+ pub fn xargo ( & self , target : & Target ) -> Option < bool > {
207+ self . bool_from_config ( target, Environment :: xargo, CrossToml :: xargo)
208+ }
203209
204- Ok ( collected)
210+ pub fn image ( & self , target : & Target ) -> Result < Option < String > > {
211+ self . string_from_config ( target, Environment :: image, CrossToml :: image)
212+ }
213+
214+ pub fn runner ( & self , target : & Target ) -> Result < Option < String > > {
215+ self . string_from_config ( target, Environment :: runner, CrossToml :: runner)
216+ }
217+
218+ pub fn env_passthrough ( & self , target : & Target ) -> Result < Vec < String > > {
219+ self . vec_from_config (
220+ target,
221+ Environment :: passthrough,
222+ CrossToml :: env_passthrough_build,
223+ CrossToml :: env_passthrough_target,
224+ )
225+ }
226+
227+ pub fn env_volumes ( & self , target : & Target ) -> Result < Vec < String > > {
228+ self . vec_from_config (
229+ target,
230+ Environment :: volumes,
231+ CrossToml :: env_volumes_build,
232+ CrossToml :: env_volumes_target,
233+ )
205234 }
206235
207236 pub fn target ( & self , target_list : & TargetList ) -> Option < Target > {
@@ -231,6 +260,7 @@ impl Config {
231260#[ cfg( test) ]
232261mod tests {
233262 use super :: * ;
263+ use crate :: errors:: * ;
234264 use crate :: { Target , TargetList } ;
235265
236266 fn target_list ( ) -> TargetList {
@@ -257,24 +287,17 @@ mod tests {
257287 map. insert ( "CROSS_BUILD_XARGO" , "tru" ) ;
258288
259289 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- }
290+ assert_eq ! ( env. xargo( & target( ) ) , ( Some ( true ) , None ) ) ;
265291 }
266292
267293 #[ test]
268- pub fn build_and_target_set_returns_tuple ( ) -> Result < ( ) > {
294+ pub fn build_and_target_set_returns_tuple ( ) {
269295 let mut map = std:: collections:: HashMap :: new ( ) ;
270296 map. insert ( "CROSS_BUILD_XARGO" , "true" ) ;
271297 map. insert ( "CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO" , "false" ) ;
272298
273299 let env = Environment :: new ( Some ( map) ) ;
274-
275- assert_eq ! ( env. xargo( & target( ) ) ?, ( Some ( true ) , Some ( false ) ) ) ;
276-
277- Ok ( ( ) )
300+ assert_eq ! ( env. xargo( & target( ) ) , ( Some ( true ) , Some ( false ) ) ) ;
278301 }
279302
280303 #[ test]
@@ -329,7 +352,7 @@ mod tests {
329352
330353 let env = Environment :: new ( Some ( map) ) ;
331354 let config = Config :: new_with ( Some ( toml ( TOML_BUILD_XARGO_FALSE ) ?) , env) ;
332- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( true ) ) ) ) ;
355+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
333356
334357 Ok ( ( ) )
335358 }
@@ -341,7 +364,7 @@ mod tests {
341364 let env = Environment :: new ( Some ( map) ) ;
342365
343366 let config = Config :: new_with ( Some ( toml ( TOML_TARGET_XARGO_FALSE ) ?) , env) ;
344- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( true ) ) ) ) ;
367+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
345368
346369 Ok ( ( ) )
347370 }
@@ -352,7 +375,7 @@ mod tests {
352375 map. insert ( "CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO" , "true" ) ;
353376 let env = Environment :: new ( Some ( map) ) ;
354377 let config = Config :: new_with ( Some ( toml ( TOML_BUILD_XARGO_FALSE ) ?) , env) ;
355- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( false ) ) ) ) ;
378+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
356379
357380 Ok ( ( ) )
358381 }
0 commit comments