use alloc::{string::String, vec::Vec};
use crate::parser::ast::Section;
use crate::parser::errors::ParseIssue;
use super::delta_eq::sections_equal_ignoring_spans;
use super::Script;
#[derive(Debug, Clone)]
pub struct ScriptDelta<'a> {
pub added: Vec<Section<'a>>,
pub modified: Vec<(usize, Section<'a>)>,
pub removed: Vec<usize>,
pub new_issues: Vec<ParseIssue>,
}
#[must_use]
pub fn calculate_delta<'a>(old_script: &Script<'a>, new_script: &Script<'a>) -> ScriptDelta<'a> {
let mut added = Vec::new();
let mut modified = Vec::new();
let mut removed = Vec::new();
let old_sections: Vec<_> = old_script.sections().iter().collect();
let new_sections: Vec<_> = new_script.sections().iter().collect();
for (idx, old_section) in old_sections.iter().enumerate() {
let old_type = old_section.section_type();
if let Some((_new_idx, new_section)) = new_sections
.iter()
.enumerate()
.find(|(_, s)| s.section_type() == old_type)
{
if !sections_equal_ignoring_spans(old_section, new_section) {
modified.push((idx, (*new_section).clone()));
}
} else {
removed.push(idx);
}
}
for new_section in &new_sections {
let new_type = new_section.section_type();
if !old_sections.iter().any(|s| s.section_type() == new_type) {
added.push((*new_section).clone());
}
}
let new_issues: Vec<_> = new_script.issues().to_vec();
ScriptDelta {
added,
modified,
removed,
new_issues,
}
}
#[derive(Debug, Clone)]
pub struct ScriptDeltaOwned {
pub added: Vec<String>,
pub modified: Vec<(usize, String)>,
pub removed: Vec<usize>,
pub new_issues: Vec<ParseIssue>,
}
impl ScriptDelta<'_> {
#[must_use]
pub fn is_empty(&self) -> bool {
self.added.is_empty()
&& self.modified.is_empty()
&& self.removed.is_empty()
&& self.new_issues.is_empty()
}
}