Skip to content

Commit 415bbd3

Browse files
committed
Replace unwieldy tuple return types in config with new dedicated type
1 parent 1826adb commit 415bbd3

File tree

3 files changed

+94
-62
lines changed

3 files changed

+94
-62
lines changed

.changes/1489.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"description": "Simplify config internals",
3+
"type": "internal"
4+
}

src/config.rs

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,37 @@ use std::collections::HashMap;
99
use std::env;
1010
use std::str::FromStr;
1111

12+
#[derive(Debug)]
13+
pub struct ConfVal<T> {
14+
pub build: Option<T>,
15+
pub target: Option<T>,
16+
}
17+
18+
impl<T> ConfVal<T> {
19+
pub fn new(build: Option<T>, target: Option<T>) -> Self {
20+
Self { build, target }
21+
}
22+
23+
pub fn map<U, F: Fn(T) -> U>(self, f: F) -> ConfVal<U> {
24+
ConfVal {
25+
build: self.build.map(&f),
26+
target: self.target.map(&f),
27+
}
28+
}
29+
}
30+
31+
impl<T> Default for ConfVal<T> {
32+
fn default() -> Self {
33+
Self::new(None, None)
34+
}
35+
}
36+
37+
impl<T: PartialEq> PartialEq<(Option<T>, Option<T>)> for ConfVal<T> {
38+
fn eq(&self, other: &(Option<T>, Option<T>)) -> bool {
39+
self.build == other.0 && self.target == other.1
40+
}
41+
}
42+
1243
#[derive(Debug)]
1344
struct Environment(&'static str, Option<HashMap<&'static str, &'static str>>);
1445

@@ -33,11 +64,11 @@ impl Environment {
3364
var: &str,
3465
target: &Target,
3566
convert: impl Fn(&str) -> T,
36-
) -> (Option<T>, Option<T>) {
67+
) -> ConfVal<T> {
3768
let build_values = self.get_build_var(var).map(|ref s| convert(s));
3869
let target_values = self.get_target_var(target, var).map(|ref s| convert(s));
3970

40-
(build_values, target_values)
71+
ConfVal::new(build_values, target_values)
4172
}
4273

4374
fn target_path(target: &Target, key: &str) -> String {
@@ -60,11 +91,11 @@ impl Environment {
6091
self.get_var(&self.build_var_name(&Self::target_path(target, key)))
6192
}
6293

63-
fn xargo(&self, target: &Target) -> (Option<bool>, Option<bool>) {
94+
fn xargo(&self, target: &Target) -> ConfVal<bool> {
6495
self.get_values_for("XARGO", target, bool_from_envvar)
6596
}
6697

67-
fn build_std(&self, target: &Target) -> (Option<BuildStd>, Option<BuildStd>) {
98+
fn build_std(&self, target: &Target) -> ConfVal<BuildStd> {
6899
self.get_values_for("BUILD_STD", target, |v| {
69100
if let Some(value) = try_bool_from_envvar(v) {
70101
BuildStd::Bool(value)
@@ -74,15 +105,15 @@ impl Environment {
74105
})
75106
}
76107

77-
fn zig(&self, target: &Target) -> (Option<bool>, Option<bool>) {
108+
fn zig(&self, target: &Target) -> ConfVal<bool> {
78109
self.get_values_for("ZIG", target, bool_from_envvar)
79110
}
80111

81-
fn zig_version(&self, target: &Target) -> (Option<String>, Option<String>) {
112+
fn zig_version(&self, target: &Target) -> ConfVal<String> {
82113
self.get_values_for("ZIG_VERSION", target, ToOwned::to_owned)
83114
}
84115

85-
fn zig_image(&self, target: &Target) -> Result<(Option<PossibleImage>, Option<PossibleImage>)> {
116+
fn zig_image(&self, target: &Target) -> Result<ConfVal<PossibleImage>> {
86117
let get_build = |env: &Environment, var: &str| env.get_build_var(var);
87118
let get_target = |env: &Environment, var: &str| env.get_target_var(target, var);
88119
let env_build = get_possible_image(
@@ -100,23 +131,23 @@ impl Environment {
100131
get_target,
101132
)?;
102133

103-
Ok((env_build, env_target))
134+
Ok(ConfVal::new(env_build, env_target))
104135
}
105136

106137
fn image(&self, target: &Target) -> Result<Option<PossibleImage>> {
107138
let get_target = |env: &Environment, var: &str| env.get_target_var(target, var);
108139
get_possible_image(self, "IMAGE", "IMAGE_TOOLCHAIN", get_target, get_target)
109140
}
110141

111-
fn dockerfile(&self, target: &Target) -> (Option<String>, Option<String>) {
142+
fn dockerfile(&self, target: &Target) -> ConfVal<String> {
112143
self.get_values_for("DOCKERFILE", target, ToOwned::to_owned)
113144
}
114145

115-
fn dockerfile_context(&self, target: &Target) -> (Option<String>, Option<String>) {
146+
fn dockerfile_context(&self, target: &Target) -> ConfVal<String> {
116147
self.get_values_for("DOCKERFILE_CONTEXT", target, ToOwned::to_owned)
117148
}
118149

119-
fn pre_build(&self, target: &Target) -> (Option<PreBuild>, Option<PreBuild>) {
150+
fn pre_build(&self, target: &Target) -> ConfVal<PreBuild> {
120151
self.get_values_for("PRE_BUILD", target, |v| {
121152
let v: Vec<_> = v.split('\n').map(String::from).collect();
122153
if v.len() == 1 {
@@ -134,11 +165,11 @@ impl Environment {
134165
self.get_target_var(target, "RUNNER")
135166
}
136167

137-
fn passthrough(&self, target: &Target) -> (Option<Vec<String>>, Option<Vec<String>>) {
168+
fn passthrough(&self, target: &Target) -> ConfVal<Vec<String>> {
138169
self.get_values_for("ENV_PASSTHROUGH", target, split_to_cloned_by_ws)
139170
}
140171

141-
fn volumes(&self, target: &Target) -> (Option<Vec<String>>, Option<Vec<String>>) {
172+
fn volumes(&self, target: &Target) -> ConfVal<Vec<String>> {
142173
self.get_values_for("ENV_VOLUMES", target, split_to_cloned_by_ws)
143174
}
144175

@@ -209,10 +240,6 @@ pub fn try_bool_from_envvar(envvar: &str) -> Option<bool> {
209240
}
210241
}
211242

212-
fn map_opt_tuple<T, U, F: Fn(T) -> U>(t: (Option<T>, Option<T>), f: F) -> (Option<U>, Option<U>) {
213-
(t.0.map(&f), t.1.map(&f))
214-
}
215-
216243
#[derive(Debug)]
217244
pub struct Config {
218245
toml: Option<CrossToml>,
@@ -250,26 +277,26 @@ impl Config {
250277
fn get_from_value_inner<T, U>(
251278
&self,
252279
target: &Target,
253-
env: impl for<'a> FnOnce(&'a Environment, &Target) -> (Option<T>, Option<T>),
254-
config: impl for<'a> FnOnce(&'a CrossToml, &Target) -> (Option<Cow<'a, U>>, Option<Cow<'a, U>>),
280+
env: impl for<'a> FnOnce(&'a Environment, &Target) -> ConfVal<T>,
281+
config: impl for<'a> FnOnce(&'a CrossToml, &Target) -> ConfVal<Cow<'a, U>>,
255282
) -> Option<T>
256283
where
257284
U: ToOwned<Owned = T> + ?Sized,
258285
{
259-
let (env_build, env_target) = env(&self.env, target);
260-
let (toml_build, toml_target) = self
286+
let env = env(&self.env, target);
287+
let toml = self
261288
.toml
262289
.as_ref()
263290
.map(|toml| config(toml, target))
264291
.unwrap_or_default();
265292

266-
match (env_target, toml_target) {
293+
match (env.target, toml.target) {
267294
(Some(value), _) => return Some(value),
268295
(None, Some(value)) => return Some(value.into_owned()),
269296
(None, None) => {}
270297
}
271298

272-
match (env_build, toml_build) {
299+
match (env.build, toml.build) {
273300
(Some(value), _) => return Some(value),
274301
(None, Some(value)) => return Some(value.into_owned()),
275302
(None, None) => {}
@@ -281,19 +308,16 @@ impl Config {
281308
fn vec_from_config(
282309
&self,
283310
target: &Target,
284-
env: impl for<'a> FnOnce(&'a Environment, &Target) -> (Option<Vec<String>>, Option<Vec<String>>),
285-
config: impl for<'a> FnOnce(
286-
&'a CrossToml,
287-
&Target,
288-
) -> (Option<&'a [String]>, Option<&'a [String]>),
311+
env: impl for<'a> FnOnce(&'a Environment, &Target) -> ConfVal<Vec<String>>,
312+
config: impl for<'a> FnOnce(&'a CrossToml, &Target) -> ConfVal<&'a [String]>,
289313
sum: bool,
290314
) -> Option<Vec<String>> {
291315
if sum {
292-
let (mut env_build, env_target) = env(&self.env, target);
293-
if let (Some(b), Some(mut t)) = (&mut env_build, env_target) {
294-
b.append(&mut t);
316+
let mut env = env(&self.env, target);
317+
if let (Some(b), Some(t)) = (&mut env.build, &mut env.target) {
318+
b.append(t);
295319
}
296-
self.sum_of_env_toml_values(env_build, |t| config(t, target))
320+
self.sum_of_env_toml_values(env.build, |t| config(t, target))
297321
} else {
298322
self.get_from_ref(target, env, config)
299323
}
@@ -302,28 +326,28 @@ impl Config {
302326
fn get_from_ref<T, U>(
303327
&self,
304328
target: &Target,
305-
env: impl for<'a> FnOnce(&'a Environment, &Target) -> (Option<T>, Option<T>),
306-
config: impl for<'a> FnOnce(&'a CrossToml, &Target) -> (Option<&'a U>, Option<&'a U>),
329+
env: impl for<'a> FnOnce(&'a Environment, &Target) -> ConfVal<T>,
330+
config: impl for<'a> FnOnce(&'a CrossToml, &Target) -> ConfVal<&'a U>,
307331
) -> Option<T>
308332
where
309333
U: ToOwned<Owned = T> + ?Sized,
310334
{
311335
self.get_from_value_inner(target, env, |toml, target| {
312-
map_opt_tuple(config(toml, target), |v| Cow::Borrowed(v))
336+
config(toml, target).map(|v| Cow::Borrowed(v))
313337
})
314338
}
315339

316340
fn get_from_value<T>(
317341
&self,
318342
target: &Target,
319-
env: impl FnOnce(&Environment, &Target) -> (Option<T>, Option<T>),
320-
config: impl FnOnce(&CrossToml, &Target) -> (Option<T>, Option<T>),
343+
env: impl FnOnce(&Environment, &Target) -> ConfVal<T>,
344+
config: impl FnOnce(&CrossToml, &Target) -> ConfVal<T>,
321345
) -> Option<T>
322346
where
323347
T: ToOwned<Owned = T>,
324348
{
325349
self.get_from_value_inner::<T, T>(target, env, |toml, target| {
326-
map_opt_tuple(config(toml, target), |v| Cow::Owned(v))
350+
config(toml, target).map(|v| Cow::Owned(v))
327351
})
328352
}
329353

@@ -357,16 +381,16 @@ impl Config {
357381
let env = self.env.image(target)?;
358382
Ok(self.get_from_ref(
359383
target,
360-
|_, _| (None, env),
361-
|toml, target| (None, toml.image(target)),
384+
|_, _| ConfVal::new(None, env),
385+
|toml, target| ConfVal::new(None, toml.image(target)),
362386
))
363387
}
364388

365389
pub fn runner(&self, target: &Target) -> Option<String> {
366390
self.get_from_ref(
367391
target,
368-
|env, target| (None, env.runner(target)),
369-
|toml, target| (None, toml.runner(target)),
392+
|env, target| ConfVal::new(None, env.runner(target)),
393+
|toml, target| ConfVal::new(None, toml.runner(target)),
370394
)
371395
}
372396

@@ -435,19 +459,19 @@ impl Config {
435459
fn sum_of_env_toml_values<'a>(
436460
&'a self,
437461
env_values: Option<Vec<String>>,
438-
toml_getter: impl FnOnce(&'a CrossToml) -> (Option<&'a [String]>, Option<&'a [String]>),
462+
toml_getter: impl FnOnce(&'a CrossToml) -> ConfVal<&'a [String]>,
439463
) -> Option<Vec<String>> {
440464
let mut defined = false;
441465
let mut collect = vec![];
442466
if env_values.is_some() {
443467
return env_values;
444-
} else if let Some((build, target)) = self.toml.as_ref().map(toml_getter) {
445-
if let Some(build) = build {
468+
} else if let Some(toml) = self.toml.as_ref().map(toml_getter) {
469+
if let Some(build) = toml.build {
446470
collect.extend(build.iter().cloned());
447471
defined = true;
448472
}
449473

450-
if let Some(target) = target {
474+
if let Some(target) = toml.target {
451475
collect.extend(target.iter().cloned());
452476
defined = true;
453477
}
@@ -564,7 +588,7 @@ mod tests {
564588

565589
let env = Environment::new(Some(map));
566590

567-
let (build, target) = env.passthrough(&target());
591+
let ConfVal { build, target } = env.passthrough(&target());
568592
assert!(build.as_ref().unwrap().contains(&"TEST1".to_owned()));
569593
assert!(build.as_ref().unwrap().contains(&"TEST2".to_owned()));
570594
assert!(target.as_ref().unwrap().contains(&"PASS1".to_owned()));

0 commit comments

Comments
 (0)