Skip to main content

ass_core/parser/script/
tracking.rs

1//! Change-tracking controls and structural diffing.
2//!
3//! Exposes the enable/disable/query surface over the script's internal
4//! [`ChangeTracker`](super::types::ChangeTracker) and the [`Script::diff`]
5//! routine that reports section-level differences between two scripts.
6
7use alloc::vec::Vec;
8
9use super::types::Change;
10use super::Script;
11
12impl<'a> Script<'a> {
13    /// Enable change tracking
14    ///
15    /// When enabled, all modifications to the script will be recorded
16    /// in the change tracker for later analysis.
17    pub fn enable_change_tracking(&mut self) {
18        self.change_tracker.enable();
19    }
20
21    /// Disable change tracking
22    ///
23    /// When disabled, modifications will not be recorded.
24    pub fn disable_change_tracking(&mut self) {
25        self.change_tracker.disable();
26    }
27
28    /// Check if change tracking is enabled
29    #[must_use]
30    pub const fn is_change_tracking_enabled(&self) -> bool {
31        self.change_tracker.is_enabled()
32    }
33
34    /// Get all recorded changes
35    ///
36    /// Returns a slice of all changes recorded since tracking was enabled
37    /// or since the last clear operation.
38    #[must_use]
39    pub fn changes(&self) -> &[Change<'a>] {
40        self.change_tracker.changes()
41    }
42
43    /// Clear all recorded changes
44    ///
45    /// Removes all changes from the tracker while keeping tracking enabled/disabled.
46    pub fn clear_changes(&mut self) {
47        self.change_tracker.clear();
48    }
49
50    /// Get the number of recorded changes
51    #[must_use]
52    pub fn change_count(&self) -> usize {
53        self.change_tracker.len()
54    }
55
56    /// Compute the difference between this script and another
57    ///
58    /// Analyzes the differences between two scripts and returns a list of changes
59    /// that would transform the other script into this one.
60    ///
61    /// # Arguments
62    ///
63    /// * `other` - The script to compare against
64    ///
65    /// # Returns
66    ///
67    /// A vector of changes representing the differences
68    #[must_use]
69    pub fn diff(&self, other: &Self) -> Vec<Change<'a>> {
70        let mut changes = Vec::new();
71
72        // Compare sections
73        let max_sections = self.sections.len().max(other.sections.len());
74
75        for i in 0..max_sections {
76            match (self.sections.get(i), other.sections.get(i)) {
77                (Some(self_section), Some(other_section)) => {
78                    // Both scripts have this section - check if they're different
79                    if self_section != other_section {
80                        // For now, record as section removed and added
81                        // In a more sophisticated implementation, we could diff the contents
82                        changes.push(Change::SectionRemoved {
83                            section_type: other_section.section_type(),
84                            index: i,
85                        });
86                        changes.push(Change::SectionAdded {
87                            section: self_section.clone(),
88                            index: i,
89                        });
90                    }
91                }
92                (Some(self_section), None) => {
93                    // Section exists in self but not in other - it was added
94                    changes.push(Change::SectionAdded {
95                        section: self_section.clone(),
96                        index: i,
97                    });
98                }
99                (None, Some(other_section)) => {
100                    // Section exists in other but not in self - it was removed
101                    changes.push(Change::SectionRemoved {
102                        section_type: other_section.section_type(),
103                        index: i,
104                    });
105                }
106                (None, None) => {
107                    // Should not happen
108                    unreachable!("max_sections calculation error");
109                }
110            }
111        }
112
113        changes
114    }
115}