zrx_stream/stream/value/
delta.rs

1// Copyright (c) Zensical LLC <https://zensical.org>
2
3// SPDX-License-Identifier: MIT
4// Third-party contributions licensed under CLA
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;
30use zrx_scheduler::effect::Item;
31use zrx_scheduler::{Id, Value};
32
33// ----------------------------------------------------------------------------
34// Structs
35// ----------------------------------------------------------------------------
36
37/// Delta of items.
38///
39/// This data type represents a collection of items that can include insertions
40/// and deletions (if [`Option`] is [`None`]), which we call deltas. Deltas are
41/// the means of differentially passing changes through a stream. They must be
42/// applied to a store to manifest the changes they represent.
43///
44/// Note that deltas are assumed to always only contain unique items, meaning
45/// there are no two items with the same identifier in a delta. This invariant
46/// must be checked with unit tests (which we provide for our operators), but
47/// is not enforced at runtime for performance reasons. Differential semantics
48/// still hold if this invariant is violated, but performance might be impacted
49/// due to unnecessary re-computations.
50///
51/// # Examples
52///
53/// ```
54/// use zrx_scheduler::effect::Item;
55/// use zrx_stream::value::Delta;
56///
57/// // Create delta of items
58/// let delta = Delta::from([
59///     Item::new("a", Some(1)),
60///     Item::new("b", Some(2)),
61///     Item::new("c", Some(3)),
62/// ]);
63/// ```
64#[derive(Clone, Debug)]
65pub struct Delta<I, T> {
66    /// Vector of items.
67    inner: Vec<Item<I, Option<T>>>,
68}
69
70// ----------------------------------------------------------------------------
71// Implementations
72// ----------------------------------------------------------------------------
73
74impl<I, T> Delta<I, T> {
75    /// Creates an iterator over the delta of items.
76    ///
77    /// # Examples
78    ///
79    /// ```
80    /// use zrx_scheduler::effect::Item;
81    /// use zrx_stream::value::Delta;
82    ///
83    /// // Create delta of items
84    /// let delta = Delta::from([
85    ///     Item::new("a", Some(1)),
86    ///     Item::new("b", Some(2)),
87    ///     Item::new("c", Some(3)),
88    /// ]);
89    ///
90    /// // Create iterator over items
91    /// for item in delta.iter() {
92    ///     println!("{item:?}");
93    /// }
94    /// ```
95    #[inline]
96    pub fn iter(&self) -> Iter<'_, Item<I, Option<T>>> {
97        self.inner.iter()
98    }
99}
100
101// ----------------------------------------------------------------------------
102// Trait implementations
103// ----------------------------------------------------------------------------
104
105impl<I, T> Value for Delta<I, T>
106where
107    I: Id,
108    T: Value,
109{
110}
111
112// ----------------------------------------------------------------------------
113
114impl<I, T, U, const N: usize> From<[U; N]> for Delta<I, T>
115where
116    U: Into<Item<I, Option<T>>>,
117{
118    /// Creates a delta of items from a slice of items.
119    ///
120    /// # Examples
121    ///
122    /// ```
123    /// use zrx_scheduler::effect::Item;
124    /// use zrx_stream::value::Delta;
125    ///
126    /// // Create delta of items
127    /// let delta = Delta::from([
128    ///     Item::new("a", Some(1)),
129    ///     Item::new("b", Some(2)),
130    ///     Item::new("c", Some(3)),
131    /// ]);
132    /// ```
133    #[inline]
134    fn from(value: [U; N]) -> Self {
135        Self::from_iter(value)
136    }
137}
138
139// ----------------------------------------------------------------------------
140
141impl<I, T, U> FromIterator<U> for Delta<I, T>
142where
143    U: Into<Item<I, Option<T>>>,
144{
145    /// Creates a delta of items from an iterator.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use zrx_scheduler::effect::Item;
151    /// use zrx_stream::value::Delta;
152    ///
153    /// // Create delta of items
154    /// let delta = Delta::from_iter([
155    ///     Item::new("a", Some(1)),
156    ///     Item::new("b", Some(2)),
157    ///     Item::new("c", Some(3)),
158    /// ]);
159    /// ```
160    #[inline]
161    fn from_iter<V>(iter: V) -> Self
162    where
163        V: IntoIterator<Item = U>,
164    {
165        Self {
166            inner: iter.into_iter().map(Into::into).collect(),
167        }
168    }
169}
170
171impl<I, T> IntoIterator for Delta<I, T> {
172    type Item = Item<I, Option<T>>;
173    type IntoIter = IntoIter<Self::Item>;
174
175    /// Creates an iterator over the delta of items.
176    ///
177    /// # Examples
178    ///
179    /// ```
180    /// use zrx_scheduler::effect::Item;
181    /// use zrx_stream::value::Delta;
182    ///
183    /// // Create delta of items
184    /// let delta = Delta::from([
185    ///     Item::new("a", Some(1)),
186    ///     Item::new("b", Some(2)),
187    ///     Item::new("c", Some(3)),
188    /// ]);
189    ///
190    /// // Create iterator over items
191    /// for item in delta {
192    ///     println!("{item:?}");
193    /// }
194    /// ```
195    #[inline]
196    fn into_iter(self) -> Self::IntoIter {
197        self.inner.into_iter()
198    }
199}
200
201impl<'a, I, T> IntoIterator for &'a Delta<I, T> {
202    type Item = &'a Item<I, Option<T>>;
203    type IntoIter = Iter<'a, Item<I, Option<T>>>;
204
205    /// Creates an iterator over the delta of items.
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// use zrx_scheduler::effect::Item;
211    /// use zrx_stream::value::Delta;
212    ///
213    /// // Create delta of items
214    /// let delta = Delta::from([
215    ///     Item::new("a", Some(1)),
216    ///     Item::new("b", Some(2)),
217    ///     Item::new("c", Some(3)),
218    /// ]);
219    ///
220    /// // Create iterator over items
221    /// for item in &delta {
222    ///     println!("{item:?}");
223    /// }
224    /// ```
225    #[inline]
226    fn into_iter(self) -> Self::IntoIter {
227        self.inner.iter()
228    }
229}
230
231// ----------------------------------------------------------------------------
232
233impl<I, T> Default for Delta<I, T> {
234    /// Creates an empty delta of items.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// use zrx_stream::value::Delta;
240    ///
241    /// // Create empty delta of items
242    /// let delta = Delta::default();
243    /// # let _: Delta<(), ()> = delta;
244    /// ```
245    #[inline]
246    fn default() -> Self {
247        Self { inner: Vec::default() }
248    }
249}