Skip to main content

ass_core/parser/streaming/delta/
batch.rs

1//! Batch collection for parse deltas
2//!
3//! Defines [`DeltaBatch`], a container that aggregates multiple [`ParseDelta`]
4//! values and exposes filtering, merging, and validation helpers.
5
6use super::ParseDelta;
7use alloc::vec::Vec;
8
9/// Collection of parse deltas with batch operations
10///
11/// Provides utilities for working with multiple deltas efficiently,
12/// including filtering, merging, and validation.
13#[derive(Debug, Clone)]
14pub struct DeltaBatch<'a> {
15    /// Collection of deltas representing changes to the script
16    deltas: Vec<ParseDelta<'a>>,
17}
18
19impl<'a> DeltaBatch<'a> {
20    /// Create new empty delta batch
21    #[must_use]
22    pub const fn new() -> Self {
23        Self { deltas: Vec::new() }
24    }
25
26    /// Create batch from existing deltas
27    #[must_use]
28    pub const fn from_deltas(deltas: Vec<ParseDelta<'a>>) -> Self {
29        Self { deltas }
30    }
31
32    /// Add delta to batch
33    pub fn push(&mut self, delta: ParseDelta<'a>) {
34        self.deltas.push(delta);
35    }
36
37    /// Extend batch with multiple deltas
38    pub fn extend(&mut self, other_deltas: impl IntoIterator<Item = ParseDelta<'a>>) {
39        self.deltas.extend(other_deltas);
40    }
41
42    /// Get all deltas
43    #[must_use]
44    #[allow(clippy::missing_const_for_fn)]
45    pub fn deltas(&self) -> &[ParseDelta<'a>] {
46        &self.deltas
47    }
48
49    /// Convert to vector of deltas
50    #[must_use]
51    pub fn into_deltas(self) -> Vec<ParseDelta<'a>> {
52        self.deltas
53    }
54
55    /// Check if batch is empty
56    #[must_use]
57    pub fn is_empty(&self) -> bool {
58        self.deltas.is_empty()
59    }
60
61    /// Get number of deltas in batch
62    #[must_use]
63    pub fn len(&self) -> usize {
64        self.deltas.len()
65    }
66
67    /// Filter deltas by predicate
68    #[must_use]
69    pub fn filter<F>(&self, predicate: F) -> Self
70    where
71        F: Fn(&ParseDelta<'a>) -> bool,
72    {
73        let filtered = self
74            .deltas
75            .iter()
76            .filter(|d| predicate(d))
77            .cloned()
78            .collect();
79        DeltaBatch::from_deltas(filtered)
80    }
81
82    /// Get only structural deltas (add/update/remove)
83    #[must_use]
84    pub fn structural_only(&self) -> Self {
85        self.filter(ParseDelta::is_structural)
86    }
87
88    /// Get only error deltas
89    #[must_use]
90    pub fn errors_only(&self) -> Self {
91        self.filter(ParseDelta::is_error)
92    }
93
94    /// Check if batch contains any errors
95    pub fn has_errors(&self) -> bool {
96        self.deltas.iter().any(ParseDelta::is_error)
97    }
98}
99
100impl Default for DeltaBatch<'_> {
101    fn default() -> Self {
102        Self::new()
103    }
104}
105
106impl<'a> FromIterator<ParseDelta<'a>> for DeltaBatch<'a> {
107    fn from_iter<T: IntoIterator<Item = ParseDelta<'a>>>(iter: T) -> Self {
108        Self::from_deltas(iter.into_iter().collect())
109    }
110}