Skip to main content

zrx_stream/stream/value/
delta.rs

1// Copyright (c) 2025-2026 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// All contributions are certified under the DCO
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Delta of items.
27
28use std::slice::Iter;
29use std::vec::IntoIter;
30
31use zrx_scheduler::effect::Item;
32use zrx_scheduler::{Id, Value};
33
34// ----------------------------------------------------------------------------
35// Structs
36// ----------------------------------------------------------------------------
37
38/// Delta of items.
39///
40/// This data type represents a collection of items that can include insertions
41/// and deletions (if [`Option`] is [`None`]), which we call deltas. Deltas are
42/// the means of differentially passing changes through a stream. They must be
43/// applied to a store to manifest the changes they represent.
44///
45/// Note that deltas are assumed to always only contain unique items, meaning
46/// there are no two items with the same identifier in a delta. This invariant
47/// must be checked with unit tests (which we provide for our operators), but
48/// is not enforced at runtime for performance reasons. Differential semantics
49/// still hold if this invariant is violated, but performance might be impacted
50/// due to unnecessary re-computations.
51///
52/// # Examples
53///
54/// ```
55/// use zrx_scheduler::effect::Item;
56/// use zrx_stream::value::Delta;
57///
58/// // Create delta of items
59/// let delta = Delta::from([
60///     Item::new("a", Some(1)),
61///     Item::new("b", Some(2)),
62///     Item::new("c", Some(3)),
63/// ]);
64/// ```
65#[derive(Clone, Debug)]
66pub struct Delta<I, T> {
67    /// Vector of items.
68    inner: Vec<Item<I, Option<T>>>,
69}
70
71// ----------------------------------------------------------------------------
72// Implementations
73// ----------------------------------------------------------------------------
74
75impl<I, T> Delta<I, T> {
76    /// Creates an iterator over the delta of items.
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// use zrx_scheduler::effect::Item;
82    /// use zrx_stream::value::Delta;
83    ///
84    /// // Create delta of items
85    /// let delta = Delta::from([
86    ///     Item::new("a", Some(1)),
87    ///     Item::new("b", Some(2)),
88    ///     Item::new("c", Some(3)),
89    /// ]);
90    ///
91    /// // Create iterator over items
92    /// for item in delta.iter() {
93    ///     println!("{item:?}");
94    /// }
95    /// ```
96    #[inline]
97    pub fn iter(&self) -> Iter<'_, Item<I, Option<T>>> {
98        self.inner.iter()
99    }
100}
101
102// ----------------------------------------------------------------------------
103// Trait implementations
104// ----------------------------------------------------------------------------
105
106impl<I, T> Value for Delta<I, T>
107where
108    I: Id,
109    T: Value,
110{
111}
112
113// ----------------------------------------------------------------------------
114
115impl<I, T, U, const N: usize> From<[U; N]> for Delta<I, T>
116where
117    U: Into<Item<I, Option<T>>>,
118{
119    /// Creates a delta of items from a slice of items.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use zrx_scheduler::effect::Item;
125    /// use zrx_stream::value::Delta;
126    ///
127    /// // Create delta of items
128    /// let delta = Delta::from([
129    ///     Item::new("a", Some(1)),
130    ///     Item::new("b", Some(2)),
131    ///     Item::new("c", Some(3)),
132    /// ]);
133    /// ```
134    #[inline]
135    fn from(value: [U; N]) -> Self {
136        Self::from_iter(value)
137    }
138}
139
140// ----------------------------------------------------------------------------
141
142impl<I, T, U> FromIterator<U> for Delta<I, T>
143where
144    U: Into<Item<I, Option<T>>>,
145{
146    /// Creates a delta of items from an iterator.
147    ///
148    /// # Examples
149    ///
150    /// ```
151    /// use zrx_scheduler::effect::Item;
152    /// use zrx_stream::value::Delta;
153    ///
154    /// // Create delta of items
155    /// let delta = Delta::from_iter([
156    ///     Item::new("a", Some(1)),
157    ///     Item::new("b", Some(2)),
158    ///     Item::new("c", Some(3)),
159    /// ]);
160    /// ```
161    #[inline]
162    fn from_iter<V>(iter: V) -> Self
163    where
164        V: IntoIterator<Item = U>,
165    {
166        Self {
167            inner: iter.into_iter().map(Into::into).collect(),
168        }
169    }
170}
171
172impl<I, T> IntoIterator for Delta<I, T> {
173    type Item = Item<I, Option<T>>;
174    type IntoIter = IntoIter<Self::Item>;
175
176    /// Creates an iterator over the delta of items.
177    ///
178    /// # Examples
179    ///
180    /// ```
181    /// use zrx_scheduler::effect::Item;
182    /// use zrx_stream::value::Delta;
183    ///
184    /// // Create delta of items
185    /// let delta = Delta::from([
186    ///     Item::new("a", Some(1)),
187    ///     Item::new("b", Some(2)),
188    ///     Item::new("c", Some(3)),
189    /// ]);
190    ///
191    /// // Create iterator over items
192    /// for item in delta {
193    ///     println!("{item:?}");
194    /// }
195    /// ```
196    #[inline]
197    fn into_iter(self) -> Self::IntoIter {
198        self.inner.into_iter()
199    }
200}
201
202impl<'a, I, T> IntoIterator for &'a Delta<I, T> {
203    type Item = &'a Item<I, Option<T>>;
204    type IntoIter = Iter<'a, Item<I, Option<T>>>;
205
206    /// Creates an iterator over the delta of items.
207    ///
208    /// # Examples
209    ///
210    /// ```
211    /// use zrx_scheduler::effect::Item;
212    /// use zrx_stream::value::Delta;
213    ///
214    /// // Create delta of items
215    /// let delta = Delta::from([
216    ///     Item::new("a", Some(1)),
217    ///     Item::new("b", Some(2)),
218    ///     Item::new("c", Some(3)),
219    /// ]);
220    ///
221    /// // Create iterator over items
222    /// for item in &delta {
223    ///     println!("{item:?}");
224    /// }
225    /// ```
226    #[inline]
227    fn into_iter(self) -> Self::IntoIter {
228        self.inner.iter()
229    }
230}
231
232// ----------------------------------------------------------------------------
233
234impl<I, T> Default for Delta<I, T> {
235    /// Creates an empty delta of items.
236    ///
237    /// # Examples
238    ///
239    /// ```
240    /// use zrx_stream::value::Delta;
241    ///
242    /// // Create empty delta of items
243    /// let delta = Delta::default();
244    /// # let _: Delta<(), ()> = delta;
245    /// ```
246    #[inline]
247    fn default() -> Self {
248        Self { inner: Vec::default() }
249    }
250}