use std::collections::BTreeMap;
use calamine::Reader;
use crate::model::{
Diagnostic, DiagnosticKind, DiagnosticLocation, DiffStage, Severity,
WorkbookChange,
};
use crate::open::OpenedWorkbook;
use crate::options::DiffOptions;
pub fn compare_workbook_metadata(
old_wb: &mut OpenedWorkbook,
new_wb: &mut OpenedWorkbook,
_opts: &DiffOptions,
diagnostics: &mut Vec<Diagnostic>,
) -> Vec<WorkbookChange> {
diff_defined_names(old_wb, new_wb, diagnostics);
diff_sheet_visibility(old_wb, new_wb, diagnostics);
Vec::new()
}
fn diff_defined_names(
old_wb: &mut OpenedWorkbook,
new_wb: &mut OpenedWorkbook,
diagnostics: &mut Vec<Diagnostic>,
) {
let old_names: BTreeMap<String, String> = old_wb.reader
.defined_names()
.iter()
.map(|(n, t)| (n.to_lowercase(), t.clone()))
.collect();
let new_names: BTreeMap<String, String> = new_wb.reader
.defined_names()
.iter()
.map(|(n, t)| (n.to_lowercase(), t.clone()))
.collect();
if !old_names.is_empty() || !new_names.is_empty() {
diagnostics.push(Diagnostic {
severity: Severity::Info,
kind: DiagnosticKind::DefinedNameScopeUnknown,
location: DiagnosticLocation {
stage: DiffStage::Metadata,
sheet_order: None,
sheet_name: None,
address: None,
},
message: "defined-name scope is unavailable in calamine 0.35; \
names are matched by normalized name only"
.into(),
});
}
for (name, target) in &new_names {
if !old_names.contains_key(name) {
diagnostics.push(Diagnostic {
severity: Severity::Info,
kind: DiagnosticKind::UnsupportedWorkbookMetadata {
category: format!("defined_name_added:{name}"),
},
location: DiagnosticLocation {
stage: DiffStage::Metadata,
sheet_order: None,
sheet_name: None,
address: None,
},
message: format!("defined name added: '{name}' → '{target}'"),
});
}
}
for (name, target) in &old_names {
if !new_names.contains_key(name) {
diagnostics.push(Diagnostic {
severity: Severity::Info,
kind: DiagnosticKind::UnsupportedWorkbookMetadata {
category: format!("defined_name_removed:{name}"),
},
location: DiagnosticLocation {
stage: DiffStage::Metadata,
sheet_order: None,
sheet_name: None,
address: None,
},
message: format!("defined name removed: '{name}' (was '{target}')"),
});
}
}
for (name, old_target) in &old_names {
if let Some(new_target) = new_names.get(name) {
if old_target != new_target {
diagnostics.push(Diagnostic {
severity: Severity::Info,
kind: DiagnosticKind::UnsupportedWorkbookMetadata {
category: format!("defined_name_changed:{name}"),
},
location: DiagnosticLocation {
stage: DiffStage::Metadata,
sheet_order: None,
sheet_name: None,
address: None,
},
message: format!(
"defined name '{name}' target changed: '{old_target}' → '{new_target}'"
),
});
}
}
}
}
fn diff_sheet_visibility(
old_wb: &mut OpenedWorkbook,
new_wb: &mut OpenedWorkbook,
diagnostics: &mut Vec<Diagnostic>,
) {
let old_vis: BTreeMap<String, String> = old_wb.reader
.sheets_metadata()
.iter()
.map(|s| (s.name.clone(), format!("{:?}", s.visible)))
.collect();
let new_vis: BTreeMap<String, String> = new_wb.reader
.sheets_metadata()
.iter()
.map(|s| (s.name.clone(), format!("{:?}", s.visible)))
.collect();
for (name, old_v) in &old_vis {
if let Some(new_v) = new_vis.get(name) {
if old_v != new_v {
diagnostics.push(Diagnostic {
severity: Severity::Info,
kind: DiagnosticKind::UnsupportedWorkbookMetadata {
category: format!("sheet_visibility_changed:{name}"),
},
location: DiagnosticLocation {
stage: DiffStage::Metadata,
sheet_order: None,
sheet_name: Some(name.clone()),
address: None,
},
message: format!(
"sheet '{name}' visibility: {old_v} → {new_v}"
),
});
}
}
}
}