zrx_stream/stream/value/chunk.rs
1// Copyright (c) 2025 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// Third-party contributions licensed under 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//! Chunk of items.
27
28use std::slice::Iter;
29use std::vec::IntoIter;
30use zrx_scheduler::effect::Item;
31use zrx_scheduler::{Id, Value};
32
33// ----------------------------------------------------------------------------
34// Type aliases
35// ----------------------------------------------------------------------------
36
37/// Chunk of items.
38///
39/// This data type represents a collection of items that are grouped together
40/// for processing. Unlike [`Delta`][], a [`Chunk`] contains items that are all
41/// present (i.e., not optional). Chunks are used to process a batch of items
42/// as a single unit, e.g., for windowing or pagination.
43///
44/// Note that chunks are assumed to always only contain unique items, meaning
45/// there are no two items with the same identifier in a chunk. 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.
48///
49/// [`Delta`]: crate::stream::value::Delta
50///
51/// # Examples
52///
53/// ```
54/// use zrx_scheduler::effect::Item;
55/// use zrx_stream::value::Chunk;
56///
57/// // Create chunk of items
58/// let chunk = Chunk::from([
59/// Item::new("a", 1),
60/// Item::new("b", 2),
61/// Item::new("c", 3),
62/// ]);
63/// ```
64#[derive(Clone, Debug, PartialEq, Eq)]
65pub struct Chunk<I, T> {
66 /// Vector of items.
67 inner: Vec<Item<I, T>>,
68}
69
70// ----------------------------------------------------------------------------
71// Implementations
72// ----------------------------------------------------------------------------
73
74impl<I, T> Chunk<I, T> {
75 /// Creates an iterator over the chunk of items.
76 ///
77 /// # Examples
78 ///
79 /// ```
80 /// use zrx_scheduler::effect::Item;
81 /// use zrx_stream::value::Chunk;
82 ///
83 /// // Create chunk of items
84 /// let chunk = Chunk::from([
85 /// Item::new("a", 1),
86 /// Item::new("b", 2),
87 /// Item::new("c", 3),
88 /// ]);
89 ///
90 /// // Create iterator over items
91 /// for item in chunk.iter() {
92 /// println!("{item:?}");
93 /// }
94 /// ```
95 #[inline]
96 pub fn iter(&self) -> Iter<'_, Item<I, T>> {
97 self.inner.iter()
98 }
99}
100
101// ----------------------------------------------------------------------------
102// Trait implementations
103// ----------------------------------------------------------------------------
104
105impl<I, T> Value for Chunk<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 Chunk<I, T>
115where
116 U: Into<Item<I, T>>,
117{
118 /// Creates a chunk of items from a slice of items.
119 ///
120 /// # Examples
121 ///
122 /// ```
123 /// use zrx_scheduler::effect::Item;
124 /// use zrx_stream::value::Chunk;
125 ///
126 /// // Create chunk of items
127 /// let chunk = Chunk::from([
128 /// Item::new("a", 1),
129 /// Item::new("b", 2),
130 /// Item::new("c", 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 Chunk<I, T>
142where
143 U: Into<Item<I, T>>,
144{
145 /// Creates a chunk of items from an iterator.
146 ///
147 /// # Examples
148 ///
149 /// ```
150 /// use zrx_scheduler::effect::Item;
151 /// use zrx_stream::value::Chunk;
152 ///
153 /// // Create chunk of items
154 /// let chunk = Chunk::from_iter([
155 /// Item::new("a", 1),
156 /// Item::new("b", 2),
157 /// Item::new("c", 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 Chunk<I, T> {
172 type Item = Item<I, T>;
173 type IntoIter = IntoIter<Self::Item>;
174
175 /// Creates an iterator over the chunk of items.
176 ///
177 /// # Examples
178 ///
179 /// ```
180 /// use zrx_scheduler::effect::Item;
181 /// use zrx_stream::value::Chunk;
182 ///
183 /// // Create chunk of items
184 /// let chunk = Chunk::from([
185 /// Item::new("a", 1),
186 /// Item::new("b", 2),
187 /// Item::new("c", 3),
188 /// ]);
189 ///
190 /// // Create iterator over items
191 /// for item in chunk.iter() {
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 Chunk<I, T> {
202 type Item = &'a Item<I, T>;
203 type IntoIter = Iter<'a, Item<I, T>>;
204
205 /// Creates an iterator over the chunk of items.
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use zrx_scheduler::effect::Item;
211 /// use zrx_stream::value::Chunk;
212 ///
213 /// // Create chunk of items
214 /// let chunk = Chunk::from([
215 /// Item::new("a", 1),
216 /// Item::new("b", 2),
217 /// Item::new("c", 3),
218 /// ]);
219 ///
220 /// // Create iterator over items
221 /// for item in &chunk {
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 Chunk<I, T> {
234 /// Creates an empty chunk of items.
235 ///
236 /// # Examples
237 ///
238 /// ```
239 /// use zrx_stream::value::Chunk;
240 ///
241 /// // Create empty chunk of items
242 /// let chunk = Chunk::default();
243 /// # let _: Chunk<(), ()> = chunk;
244 /// ```
245 #[inline]
246 fn default() -> Self {
247 Self { inner: Vec::default() }
248 }
249}