Skip to content

Commit 1850029

Browse files
committed
refactor: switch to Vec<ConfigValue> for ConfigValue::List
This is a preparation for supporting list of types other than string.
1 parent 341962a commit 1850029

File tree

4 files changed

+75
-31
lines changed

4 files changed

+75
-31
lines changed

src/cargo/ops/cargo_config.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,13 @@ fn print_toml(gctx: &GlobalContext, opts: &GetOptions<'_>, key: &ConfigKey, cv:
128128
CV::List(vals, _def) => {
129129
if opts.show_origin {
130130
drop_println!(gctx, "{} = [", key);
131-
for (val, def) in vals {
131+
for cv in vals {
132+
let (val, def) = match cv {
133+
CV::String(s, def) => (s.as_str(), def),
134+
// This is actually unreachable until we start supporting list of different types.
135+
// It should be validated already during the deserialization.
136+
v => todo!("support {} type ", v.desc()),
137+
};
132138
drop_println!(
133139
gctx,
134140
" {}, # {}",
@@ -139,7 +145,15 @@ fn print_toml(gctx: &GlobalContext, opts: &GetOptions<'_>, key: &ConfigKey, cv:
139145
}
140146
drop_println!(gctx, "]");
141147
} else {
142-
let vals: toml_edit::Array = vals.iter().map(|x| &x.0).collect();
148+
let vals: toml_edit::Array = vals
149+
.iter()
150+
.map(|cv| match cv {
151+
CV::String(s, _) => toml_edit::Value::from(s.as_str()),
152+
// This is actually unreachable until we start supporting list of different types.
153+
// It should be validated already during the deserialization.
154+
v => todo!("support {} type ", v.desc()),
155+
})
156+
.collect();
143157
drop_println!(gctx, "{} = {}", key, vals);
144158
}
145159
}
@@ -204,7 +218,7 @@ fn print_json(gctx: &GlobalContext, key: &ConfigKey, cv: &CV, include_key: bool)
204218
CV::Integer(val, _def) => json!(val),
205219
CV::String(val, _def) => json!(val),
206220
CV::List(vals, _def) => {
207-
let jvals: Vec<_> = vals.iter().map(|(val, _def)| json!(val)).collect();
221+
let jvals: Vec<_> = vals.iter().map(cv_to_json).collect();
208222
json!(jvals)
209223
}
210224
CV::Table(map, _def) => {

src/cargo/util/context/de.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
160160
match self.gctx.get_cv(&self.key)? {
161161
Some(CV::List(val, _def)) => res.extend(val),
162162
Some(CV::String(val, def)) => {
163-
let split_vs = val.split_whitespace().map(|s| (s.to_string(), def.clone()));
163+
let split_vs = val
164+
.split_whitespace()
165+
.map(|s| CV::String(s.to_string(), def.clone()));
164166
res.extend(split_vs);
165167
}
166168
Some(val) => {
@@ -172,7 +174,13 @@ impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
172174

173175
self.gctx.get_env_list(&self.key, &mut res)?;
174176

175-
let vals: Vec<String> = res.into_iter().map(|vd| vd.0).collect();
177+
let vals: Vec<String> = res
178+
.into_iter()
179+
.map(|val| match val {
180+
CV::String(s, _defintion) => Ok(s),
181+
other => Err(ConfigError::expected(&self.key, "string", &other)),
182+
})
183+
.collect::<Result<_, _>>()?;
176184
visitor.visit_newtype_struct(vals.into_deserializer())
177185
} else {
178186
visitor.visit_newtype_struct(self)
@@ -396,7 +404,9 @@ impl<'de, 'gctx> de::MapAccess<'de> for ConfigMapAccess<'gctx> {
396404
}
397405

398406
struct ConfigSeqAccess {
399-
list_iter: vec::IntoIter<(String, Definition)>,
407+
/// The config key to the sequence.
408+
key: ConfigKey,
409+
list_iter: vec::IntoIter<CV>,
400410
}
401411

402412
impl ConfigSeqAccess {
@@ -416,6 +426,7 @@ impl ConfigSeqAccess {
416426
de.gctx.get_env_list(&de.key, &mut res)?;
417427

418428
Ok(ConfigSeqAccess {
429+
key: de.key,
419430
list_iter: res.into_iter(),
420431
})
421432
}
@@ -430,12 +441,13 @@ impl<'de> de::SeqAccess<'de> for ConfigSeqAccess {
430441
{
431442
match self.list_iter.next() {
432443
// TODO: add `def` to error?
433-
Some((value, def)) => {
444+
Some(CV::String(value, def)) => {
434445
// This might be a String or a Value<String>.
435446
// ValueDeserializer will handle figuring out which one it is.
436447
let maybe_value_de = ValueDeserializer::new_with_string(value, def);
437448
seed.deserialize(maybe_value_de).map(Some)
438449
}
450+
Some(val) => Err(ConfigError::expected(&self.key, "list of string", &val)),
439451
None => Ok(None),
440452
}
441453
}

src/cargo/util/context/mod.rs

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -989,11 +989,7 @@ impl GlobalContext {
989989

990990
/// Internal method for getting an environment variable as a list.
991991
/// If the key is a non-mergeable list and a value is found in the environment, existing values are cleared.
992-
fn get_env_list(
993-
&self,
994-
key: &ConfigKey,
995-
output: &mut Vec<(String, Definition)>,
996-
) -> CargoResult<()> {
992+
fn get_env_list(&self, key: &ConfigKey, output: &mut Vec<ConfigValue>) -> CargoResult<()> {
997993
let Some(env_val) = self.env.get_str(key.as_env_key()) else {
998994
self.check_environment_key_case_mismatch(key);
999995
return Ok(());
@@ -1018,16 +1014,16 @@ impl GlobalContext {
10181014
def.clone(),
10191015
)
10201016
})?;
1021-
output.push((s.to_string(), def.clone()));
1017+
output.push(CV::String(s.to_string(), def.clone()))
10221018
}
10231019
} else {
10241020
output.extend(
10251021
env_val
10261022
.split_whitespace()
1027-
.map(|s| (s.to_string(), def.clone())),
1023+
.map(|s| CV::String(s.to_string(), def.clone())),
10281024
);
10291025
}
1030-
output.sort_by(|a, b| a.1.cmp(&b.1));
1026+
output.sort_by(|a, b| a.definition().cmp(b.definition()));
10311027
Ok(())
10321028
}
10331029

@@ -1386,7 +1382,16 @@ impl GlobalContext {
13861382
Some(CV::String(s, def)) => {
13871383
vec![abs(s, def)]
13881384
}
1389-
Some(CV::List(list, _def)) => list.iter().map(|(s, def)| abs(s, def)).collect(),
1385+
Some(CV::List(list, _def)) => list
1386+
.iter()
1387+
.map(|cv| match cv {
1388+
CV::String(s, def) => Ok(abs(s, def)),
1389+
other => bail!(
1390+
"`include` expected a string or list of strings, but found {} in list",
1391+
other.desc()
1392+
),
1393+
})
1394+
.collect::<CargoResult<Vec<_>>>()?,
13901395
Some(other) => bail!(
13911396
"`include` expected a string or list, but found {} in `{}`",
13921397
other.desc(),
@@ -1774,7 +1779,16 @@ impl GlobalContext {
17741779
let key = ConfigKey::from_str("paths");
17751780
// paths overrides cannot be set via env config, so use get_cv here.
17761781
match self.get_cv(&key)? {
1777-
Some(CV::List(val, definition)) => Ok(Some(Value { val, definition })),
1782+
Some(CV::List(val, definition)) => {
1783+
let val = val
1784+
.into_iter()
1785+
.map(|cv| match cv {
1786+
CV::String(s, def) => Ok((s, def)),
1787+
other => self.expected("string", &key, &other),
1788+
})
1789+
.collect::<CargoResult<Vec<_>>>()?;
1790+
Ok(Some(Value { val, definition }))
1791+
}
17781792
Some(val) => self.expected("list", &key, &val),
17791793
None => Ok(None),
17801794
}
@@ -2138,7 +2152,7 @@ enum KeyOrIdx {
21382152
pub enum ConfigValue {
21392153
Integer(i64, Definition),
21402154
String(String, Definition),
2141-
List(Vec<(String, Definition)>, Definition),
2155+
List(Vec<ConfigValue>, Definition),
21422156
Table(HashMap<String, ConfigValue>, Definition),
21432157
Boolean(bool, Definition),
21442158
}
@@ -2151,11 +2165,11 @@ impl fmt::Debug for ConfigValue {
21512165
CV::String(s, def) => write!(f, "{} (from {})", s, def),
21522166
CV::List(list, def) => {
21532167
write!(f, "[")?;
2154-
for (i, (s, def)) in list.iter().enumerate() {
2168+
for (i, item) in list.iter().enumerate() {
21552169
if i > 0 {
21562170
write!(f, ", ")?;
21572171
}
2158-
write!(f, "{} (from {})", s, def)?;
2172+
write!(f, "{item:?}")?;
21592173
}
21602174
write!(f, "] (from {})", def)
21612175
}
@@ -2196,7 +2210,7 @@ impl ConfigValue {
21962210
val.into_iter()
21972211
.enumerate()
21982212
.map(|(i, toml)| match toml {
2199-
toml::Value::String(val) => Ok((val, def.clone())),
2213+
toml::Value::String(val) => Ok(CV::String(val, def.clone())),
22002214
v => {
22012215
path.push(KeyOrIdx::Idx(i));
22022216
bail!("expected string but found {} at index {i}", v.type_str())
@@ -2231,9 +2245,7 @@ impl ConfigValue {
22312245
CV::Boolean(s, _) => toml::Value::Boolean(s),
22322246
CV::String(s, _) => toml::Value::String(s),
22332247
CV::Integer(i, _) => toml::Value::Integer(i),
2234-
CV::List(l, _) => {
2235-
toml::Value::Array(l.into_iter().map(|(s, _)| toml::Value::String(s)).collect())
2236-
}
2248+
CV::List(l, _) => toml::Value::Array(l.into_iter().map(|cv| cv.into_toml()).collect()),
22372249
CV::Table(l, _) => {
22382250
toml::Value::Table(l.into_iter().map(|(k, v)| (k, v.into_toml())).collect())
22392251
}
@@ -2275,7 +2287,7 @@ impl ConfigValue {
22752287
mem::swap(new, old);
22762288
}
22772289
}
2278-
old.sort_by(|a, b| a.1.cmp(&b.1));
2290+
old.sort_by(|a, b| a.definition().cmp(b.definition()));
22792291
}
22802292
(&mut CV::Table(ref mut old, _), CV::Table(ref mut new, _)) => {
22812293
for (key, value) in mem::take(new) {
@@ -2344,9 +2356,15 @@ impl ConfigValue {
23442356
}
23452357
}
23462358

2347-
pub fn list(&self, key: &str) -> CargoResult<&[(String, Definition)]> {
2359+
pub fn list(&self, key: &str) -> CargoResult<Vec<(String, Definition)>> {
23482360
match self {
2349-
CV::List(list, _) => Ok(list),
2361+
CV::List(list, _) => list
2362+
.iter()
2363+
.map(|cv| match cv {
2364+
CV::String(s, def) => Ok((s.clone(), def.clone())),
2365+
_ => self.expected("string", key),
2366+
})
2367+
.collect::<CargoResult<_>>(),
23502368
_ => self.expected("list", key),
23512369
}
23522370
}

src/cargo/util/context/target.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,11 @@ fn parse_links_overrides(
238238
Ok(links_overrides)
239239
}
240240

241-
fn extra_link_args<'a>(
241+
fn extra_link_args(
242242
link_type: LinkArgTarget,
243243
key: &str,
244-
value: &'a CV,
245-
) -> CargoResult<impl Iterator<Item = (LinkArgTarget, String)> + 'a> {
244+
value: &CV,
245+
) -> CargoResult<Vec<(LinkArgTarget, String)>> {
246246
let args = value.list(key)?;
247-
Ok(args.iter().map(move |v| (link_type.clone(), v.0.clone())))
247+
Ok(args.into_iter().map(|v| (link_type.clone(), v.0)).collect())
248248
}

0 commit comments

Comments
 (0)