#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Uncertainty {
Confirmed,
Candidate {
reason: String,
},
Ambiguous {
reason: String,
},
Unresolved {
reason: String,
},
Unsupported {
reason: String,
},
Excluded {
reason: String,
},
Stale {
reason: String,
},
Incomplete {
reason: String,
},
}
impl Uncertainty {
pub fn label(&self) -> &'static str {
match self {
Uncertainty::Confirmed => "confirmed",
Uncertainty::Candidate { .. } => "candidate",
Uncertainty::Ambiguous { .. } => "ambiguous",
Uncertainty::Unresolved { .. } => "unresolved",
Uncertainty::Unsupported { .. } => "unsupported",
Uncertainty::Excluded { .. } => "excluded",
Uncertainty::Stale { .. } => "stale",
Uncertainty::Incomplete { .. } => "incomplete",
}
}
pub fn reason(&self) -> Option<&str> {
match self {
Uncertainty::Confirmed => None,
Uncertainty::Candidate { reason }
| Uncertainty::Ambiguous { reason }
| Uncertainty::Unresolved { reason }
| Uncertainty::Unsupported { reason }
| Uncertainty::Excluded { reason }
| Uncertainty::Stale { reason }
| Uncertainty::Incomplete { reason } => Some(reason),
}
}
pub fn from_label(label: &str, reason: Option<String>) -> Result<Uncertainty, String> {
match label {
"confirmed" => Ok(Uncertainty::Confirmed),
"candidate" => require_reason(reason).map(|reason| Uncertainty::Candidate { reason }),
"ambiguous" => require_reason(reason).map(|reason| Uncertainty::Ambiguous { reason }),
"unresolved" => require_reason(reason).map(|reason| Uncertainty::Unresolved { reason }),
"unsupported" => {
require_reason(reason).map(|reason| Uncertainty::Unsupported { reason })
}
"excluded" => require_reason(reason).map(|reason| Uncertainty::Excluded { reason }),
"stale" => require_reason(reason).map(|reason| Uncertainty::Stale { reason }),
"incomplete" => require_reason(reason).map(|reason| Uncertainty::Incomplete { reason }),
other => Err(format!("unknown uncertainty state '{other}'")),
}
}
}
fn require_reason(reason: Option<String>) -> Result<String, String> {
match reason {
Some(reason) if !reason.trim().is_empty() => Ok(reason),
_ => Err("a non-confirmed uncertainty state requires a reason".to_string()),
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContextHealth {
Complete,
Partial {
reason: String,
},
Failed {
reason: String,
},
Unsupported {
reason: String,
},
Excluded {
reason: String,
},
}
impl ContextHealth {
pub fn label(&self) -> &'static str {
match self {
ContextHealth::Complete => "complete",
ContextHealth::Partial { .. } => "partial",
ContextHealth::Failed { .. } => "failed",
ContextHealth::Unsupported { .. } => "unsupported",
ContextHealth::Excluded { .. } => "excluded",
}
}
pub fn is_complete(&self) -> bool {
matches!(self, ContextHealth::Complete)
}
pub fn from_label(label: &str, reason: Option<String>) -> Result<ContextHealth, String> {
match label {
"complete" => Ok(ContextHealth::Complete),
"partial" => require_reason(reason).map(|reason| ContextHealth::Partial { reason }),
"failed" => require_reason(reason).map(|reason| ContextHealth::Failed { reason }),
"unsupported" => {
require_reason(reason).map(|reason| ContextHealth::Unsupported { reason })
}
"excluded" => require_reason(reason).map(|reason| ContextHealth::Excluded { reason }),
other => Err(format!("unknown context health '{other}'")),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn confirmed_needs_no_reason_but_every_other_state_does() {
assert_eq!(
Uncertainty::from_label("confirmed", None),
Ok(Uncertainty::Confirmed)
);
assert!(Uncertainty::from_label("stale", None).is_err());
assert_eq!(
Uncertainty::from_label("stale", Some("dependency compilation changed".to_string())),
Ok(Uncertainty::Stale {
reason: "dependency compilation changed".to_string()
})
);
}
#[test]
fn a_failed_or_partial_context_is_never_complete() {
let partial =
ContextHealth::from_label("partial", Some("one project missing".to_string())).unwrap();
assert!(!partial.is_complete());
assert!(ContextHealth::Complete.is_complete());
}
#[test]
fn unknown_label_is_refused() {
assert!(Uncertainty::from_label("bogus", None).is_err());
assert!(ContextHealth::from_label("bogus", None).is_err());
}
}