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