Skip to content

Commit 10f7fea

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 858371e commit 10f7fea

File tree

1 file changed

+29
-39
lines changed

1 file changed

+29
-39
lines changed

src/cargo/util/context/mod.rs

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,14 +2823,11 @@ pub struct TermConfig {
28232823
pub color: Option<String>,
28242824
pub hyperlinks: Option<bool>,
28252825
pub unicode: Option<bool>,
2826-
#[serde(deserialize_with = "progress_or_string")]
28272826
pub progress: Option<ProgressConfig>,
28282827
}
28292828

2830-
#[derive(Debug, Default, Deserialize)]
2831-
#[serde(rename_all = "kebab-case")]
2829+
#[derive(Debug, Default)]
28322830
pub struct ProgressConfig {
2833-
#[serde(default)]
28342831
pub when: ProgressWhen,
28352832
pub width: Option<usize>,
28362833
/// Communicate progress status with a terminal
@@ -2846,46 +2843,39 @@ pub enum ProgressWhen {
28462843
Always,
28472844
}
28482845

2849-
fn progress_or_string<'de, D>(deserializer: D) -> Result<Option<ProgressConfig>, D::Error>
2850-
where
2851-
D: serde::de::Deserializer<'de>,
2852-
{
2853-
struct ProgressVisitor;
2854-
2855-
impl<'de> serde::de::Visitor<'de> for ProgressVisitor {
2856-
type Value = Option<ProgressConfig>;
2857-
2858-
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2859-
formatter.write_str("a string (\"auto\" or \"never\") or a table")
2860-
}
2861-
2862-
fn visit_none<E>(self) -> Result<Self::Value, E>
2863-
where
2864-
E: serde::de::Error,
2865-
{
2866-
Ok(None)
2846+
// We need this custom deserialization for validadting the rule of
2847+
// `when = "always"` requiring a `width` field.
2848+
impl<'de> Deserialize<'de> for ProgressConfig {
2849+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2850+
where
2851+
D: serde::Deserializer<'de>,
2852+
{
2853+
#[derive(Deserialize)]
2854+
#[serde(rename_all = "kebab-case")]
2855+
struct ProgressConfigInner {
2856+
#[serde(default)]
2857+
when: ProgressWhen,
2858+
width: Option<usize>,
2859+
term_integration: Option<bool>,
28672860
}
28682861

2869-
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
2870-
where
2871-
D: serde::de::Deserializer<'de>,
2862+
let pc = ProgressConfigInner::deserialize(deserializer)?;
2863+
if let ProgressConfigInner {
2864+
when: ProgressWhen::Always,
2865+
width: None,
2866+
..
2867+
} = pc
28722868
{
2873-
let pc = ProgressConfig::deserialize(deserializer)?;
2874-
if let ProgressConfig {
2875-
when: ProgressWhen::Always,
2876-
width: None,
2877-
..
2878-
} = pc
2879-
{
2880-
return Err(serde::de::Error::custom(
2881-
"\"always\" progress requires a `width` key",
2882-
));
2883-
}
2884-
Ok(Some(pc))
2869+
return Err(serde::de::Error::custom(
2870+
"\"always\" progress requires a `width` key",
2871+
));
28852872
}
2873+
Ok(ProgressConfig {
2874+
when: pc.when,
2875+
width: pc.width,
2876+
term_integration: pc.term_integration,
2877+
})
28862878
}
2887-
2888-
deserializer.deserialize_option(ProgressVisitor)
28892879
}
28902880

28912881
#[derive(Debug)]

0 commit comments

Comments
 (0)