use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "status", content = "value")]
pub enum DeadExportsStatus {
Measured(u64),
SkippedDueToReExports,
NotApplicable,
}
impl DeadExportsStatus {
pub fn label(&self) -> String {
match self {
Self::Measured(n) => format!("{n} (RepoVerified)"),
Self::SkippedDueToReExports => "not_measured (use-graph counts `pub use` \
re-exports as live — known limitation; run `loct dead` for current count)"
.to_string(),
Self::NotApplicable => "not_applicable for this language set".to_string(),
}
}
#[cfg(test)]
pub fn is_measured(&self) -> bool {
matches!(self, Self::Measured(_))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "status", content = "value")]
pub enum MeasurementStatus {
Measured(u64),
NotMeasured(String),
NotApplicable,
}
impl MeasurementStatus {
pub fn label(&self) -> String {
match self {
Self::Measured(n) => format!("{n}"),
Self::NotMeasured(reason) => format!("not_measured ({reason})"),
Self::NotApplicable => "not_applicable".to_string(),
}
}
pub fn is_measured(&self) -> bool {
matches!(self, Self::Measured(_))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dead_exports_measured_label_carries_authority() {
let s = DeadExportsStatus::Measured(7);
assert!(s.is_measured());
let label = s.label();
assert!(label.contains('7'));
assert!(label.contains("RepoVerified"));
}
#[test]
fn dead_exports_skipped_label_explains_limitation() {
let s = DeadExportsStatus::SkippedDueToReExports;
assert!(!s.is_measured());
let label = s.label();
assert!(label.contains("not_measured"));
assert!(label.contains("re-exports"));
assert!(label.contains("loct dead"));
}
#[test]
fn dead_exports_not_applicable_label_states_reason() {
let s = DeadExportsStatus::NotApplicable;
assert!(!s.is_measured());
let label = s.label();
assert!(label.contains("not_applicable"));
}
#[test]
fn measurement_status_round_trip() {
let original = MeasurementStatus::NotMeasured("snapshot stale".to_string());
let json = serde_json::to_string(&original).expect("serialize");
let back: MeasurementStatus = serde_json::from_str(&json).expect("deserialize");
assert_eq!(original, back);
}
#[test]
fn measurement_status_label_renders_each_variant() {
assert_eq!(MeasurementStatus::Measured(3).label(), "3");
assert!(
MeasurementStatus::NotMeasured("reason".to_string())
.label()
.starts_with("not_measured")
);
assert_eq!(MeasurementStatus::NotApplicable.label(), "not_applicable");
}
#[test]
fn dead_exports_status_serde_round_trip_for_all_variants() {
for sample in [
DeadExportsStatus::Measured(0),
DeadExportsStatus::Measured(42),
DeadExportsStatus::SkippedDueToReExports,
DeadExportsStatus::NotApplicable,
] {
let json = serde_json::to_string(&sample).expect("serialize");
let back: DeadExportsStatus = serde_json::from_str(&json).expect("deserialize");
assert_eq!(sample, back);
}
}
}