Skip to content

Commit eb0e92f

Browse files
committed
refactor(gctx): impl Deserialize directly for ProgressConfig
This makes the deserialization logic embedded in type itself, rather than relying on parent struct
1 parent e572672 commit eb0e92f

File tree

1 file changed

+29
-40
lines changed

1 file changed

+29
-40
lines changed

src/cargo/util/context/schema.rs

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use std::borrow::Cow;
1414
use std::collections::HashMap;
1515
use std::ffi::OsStr;
16-
use std::fmt;
1716

1817
use serde::Deserialize;
1918
use serde_untagged::UntaggedEnumVisitor;
@@ -350,7 +349,6 @@ pub struct TermConfig {
350349
pub color: Option<String>,
351350
pub hyperlinks: Option<bool>,
352351
pub unicode: Option<bool>,
353-
#[serde(deserialize_with = "progress_or_string")]
354352
pub progress: Option<ProgressConfig>,
355353
}
356354

@@ -368,10 +366,8 @@ pub struct TermConfig {
368366
/// [term]
369367
/// progress = { when = "always", width = 80 }
370368
/// ```
371-
#[derive(Debug, Default, Deserialize)]
372-
#[serde(rename_all = "kebab-case")]
369+
#[derive(Debug, Default)]
373370
pub struct ProgressConfig {
374-
#[serde(default)]
375371
pub when: ProgressWhen,
376372
pub width: Option<usize>,
377373
/// Communicate progress status with a terminal
@@ -387,46 +383,39 @@ pub enum ProgressWhen {
387383
Always,
388384
}
389385

390-
fn progress_or_string<'de, D>(deserializer: D) -> Result<Option<ProgressConfig>, D::Error>
391-
where
392-
D: serde::de::Deserializer<'de>,
393-
{
394-
struct ProgressVisitor;
395-
396-
impl<'de> serde::de::Visitor<'de> for ProgressVisitor {
397-
type Value = Option<ProgressConfig>;
398-
399-
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
400-
formatter.write_str("a table")
401-
}
402-
403-
fn visit_none<E>(self) -> Result<Self::Value, E>
404-
where
405-
E: serde::de::Error,
406-
{
407-
Ok(None)
386+
// We need this custom deserialization for validadting the rule of
387+
// `when = "always"` requiring a `width` field.
388+
impl<'de> Deserialize<'de> for ProgressConfig {
389+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
390+
where
391+
D: serde::Deserializer<'de>,
392+
{
393+
#[derive(Deserialize)]
394+
#[serde(rename_all = "kebab-case")]
395+
struct ProgressConfigInner {
396+
#[serde(default)]
397+
when: ProgressWhen,
398+
width: Option<usize>,
399+
term_integration: Option<bool>,
408400
}
409401

410-
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
411-
where
412-
D: serde::de::Deserializer<'de>,
402+
let pc = ProgressConfigInner::deserialize(deserializer)?;
403+
if let ProgressConfigInner {
404+
when: ProgressWhen::Always,
405+
width: None,
406+
..
407+
} = pc
413408
{
414-
let pc = ProgressConfig::deserialize(deserializer)?;
415-
if let ProgressConfig {
416-
when: ProgressWhen::Always,
417-
width: None,
418-
..
419-
} = pc
420-
{
421-
return Err(serde::de::Error::custom(
422-
"\"always\" progress requires a `width` key",
423-
));
424-
}
425-
Ok(Some(pc))
409+
return Err(serde::de::Error::custom(
410+
"\"always\" progress requires a `width` key",
411+
));
426412
}
413+
Ok(ProgressConfig {
414+
when: pc.when,
415+
width: pc.width,
416+
term_integration: pc.term_integration,
417+
})
427418
}
428-
429-
deserializer.deserialize_option(ProgressVisitor)
430419
}
431420

432421
#[derive(Debug)]

0 commit comments

Comments
 (0)