rust_lodash/collection/mod.rs
1/*!
2Collection module for Lodash-RS.
3
4This module contains the core collection types and all collection methods
5organized by functionality.
6*/
7
8pub mod iteration;
9pub mod query;
10pub mod transform;
11pub mod operation;
12pub mod async_support;
13
14// Note: These imports are kept for future use in error handling
15// use crate::utils::{LodashError, Result};
16
17/// Core collection type that wraps a vector of items.
18///
19/// This is the main type used throughout Lodash-RS for collection operations.
20/// It provides a type-safe wrapper around `Vec<T>` with additional functionality.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct Collection<T> {
23 /// The underlying data
24 data: Vec<T>,
25}
26
27impl<T> Collection<T> {
28 /// Create a new collection from an iterator.
29 ///
30 /// # Examples
31 ///
32 /// ```
33 /// use rust_lodash::collection::Collection;
34 ///
35 /// let collection = Collection::new(vec![1, 2, 3]);
36 /// assert_eq!(collection.len(), 3);
37 /// ```
38 pub fn new(data: impl IntoIterator<Item = T>) -> Self {
39 Self {
40 data: data.into_iter().collect(),
41 }
42 }
43
44 /// Create a new empty collection.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use rust_lodash::collection::Collection;
50 ///
51 /// let collection: Collection<i32> = Collection::empty();
52 /// assert!(collection.is_empty());
53 /// ```
54 #[must_use]
55 pub fn empty() -> Self {
56 Self { data: Vec::new() }
57 }
58
59 /// Get the length of the collection.
60 ///
61 /// # Examples
62 ///
63 /// ```
64 /// use rust_lodash::collection::Collection;
65 ///
66 /// let collection = Collection::new(vec![1, 2, 3]);
67 /// assert_eq!(collection.len(), 3);
68 /// ```
69 #[must_use]
70 pub fn len(&self) -> usize {
71 self.data.len()
72 }
73
74 /// Check if the collection is empty.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use rust_lodash::collection::Collection;
80 ///
81 /// let collection: Collection<i32> = Collection::empty();
82 /// assert!(collection.is_empty());
83 ///
84 /// let collection = Collection::new(vec![1, 2, 3]);
85 /// assert!(!collection.is_empty());
86 /// ```
87 #[must_use]
88 pub fn is_empty(&self) -> bool {
89 self.data.is_empty()
90 }
91
92 /// Get a reference to the underlying data.
93 ///
94 /// # Examples
95 ///
96 /// ```
97 /// use rust_lodash::collection::Collection;
98 ///
99 /// let collection = Collection::new(vec![1, 2, 3]);
100 /// assert_eq!(collection.data(), &vec![1, 2, 3]);
101 /// ```
102 #[must_use]
103 pub fn data(&self) -> &Vec<T> {
104 &self.data
105 }
106
107 /// Get a mutable reference to the underlying data.
108 ///
109 /// # Examples
110 ///
111 /// ```
112 /// use rust_lodash::collection::Collection;
113 ///
114 /// let mut collection = Collection::new(vec![1, 2, 3]);
115 /// collection.data_mut().push(4);
116 /// assert_eq!(collection.data(), &vec![1, 2, 3, 4]);
117 /// ```
118 pub fn data_mut(&mut self) -> &mut Vec<T> {
119 &mut self.data
120 }
121
122 /// Get an item at the specified index.
123 ///
124 /// # Examples
125 ///
126 /// ```
127 /// use rust_lodash::collection::Collection;
128 ///
129 /// let collection = Collection::new(vec![1, 2, 3]);
130 /// assert_eq!(collection.get(1), Some(&2));
131 /// assert_eq!(collection.get(5), None);
132 /// ```
133 #[must_use]
134 pub fn get(&self, index: usize) -> Option<&T> {
135 self.data.get(index)
136 }
137
138 /// Get a mutable item at the specified index.
139 ///
140 /// # Examples
141 ///
142 /// ```
143 /// use rust_lodash::collection::Collection;
144 ///
145 /// let mut collection = Collection::new(vec![1, 2, 3]);
146 /// if let Some(item) = collection.get_mut(1) {
147 /// *item = 42;
148 /// }
149 /// assert_eq!(collection.get(1), Some(&42));
150 /// ```
151 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
152 self.data.get_mut(index)
153 }
154
155 /// Get the first item in the collection.
156 ///
157 /// # Examples
158 ///
159 /// ```
160 /// use rust_lodash::collection::Collection;
161 ///
162 /// let collection = Collection::new(vec![1, 2, 3]);
163 /// assert_eq!(collection.first(), Some(&1));
164 ///
165 /// let empty: Collection<i32> = Collection::empty();
166 /// assert_eq!(empty.first(), None);
167 /// ```
168 #[must_use]
169 pub fn first(&self) -> Option<&T> {
170 self.data.first()
171 }
172
173 /// Get the last item in the collection.
174 ///
175 /// # Examples
176 ///
177 /// ```
178 /// use rust_lodash::collection::Collection;
179 ///
180 /// let collection = Collection::new(vec![1, 2, 3]);
181 /// assert_eq!(collection.last(), Some(&3));
182 ///
183 /// let empty: Collection<i32> = Collection::empty();
184 /// assert_eq!(empty.last(), None);
185 /// ```
186 #[must_use]
187 pub fn last(&self) -> Option<&T> {
188 self.data.last()
189 }
190
191 /// Convert the collection to a vector.
192 ///
193 /// # Examples
194 ///
195 /// ```
196 /// use rust_lodash::collection::Collection;
197 ///
198 /// let collection = Collection::new(vec![1, 2, 3]);
199 /// let vec = collection.into_vec();
200 /// assert_eq!(vec, vec![1, 2, 3]);
201 /// ```
202 #[must_use]
203 pub fn into_vec(self) -> Vec<T> {
204 self.data
205 }
206
207 /// Convert the collection to an iterator.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// use rust_lodash::collection::Collection;
213 ///
214 /// let collection = Collection::new(vec![1, 2, 3]);
215 /// let sum: i32 = collection.into_iter().sum();
216 /// assert_eq!(sum, 6);
217 /// ```
218 #[must_use]
219 #[allow(clippy::should_implement_trait)]
220 pub fn into_iter(self) -> std::vec::IntoIter<T> {
221 self.data.into_iter()
222 }
223
224 /// Get an iterator over references to the items.
225 ///
226 /// # Examples
227 ///
228 /// ```
229 /// use rust_lodash::collection::Collection;
230 ///
231 /// let collection = Collection::new(vec![1, 2, 3]);
232 /// let sum: i32 = collection.iter().sum();
233 /// assert_eq!(sum, 6);
234 /// ```
235 pub fn iter(&self) -> std::slice::Iter<'_, T> {
236 self.data.iter()
237 }
238
239 /// Get a mutable iterator over references to the items.
240 ///
241 /// # Examples
242 ///
243 /// ```
244 /// use rust_lodash::collection::Collection;
245 ///
246 /// let mut collection = Collection::new(vec![1, 2, 3]);
247 /// for item in collection.iter_mut() {
248 /// *item *= 2;
249 /// }
250 /// assert_eq!(collection.data(), &vec![2, 4, 6]);
251 /// ```
252 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
253 self.data.iter_mut()
254 }
255}
256
257impl<T> From<Vec<T>> for Collection<T> {
258 fn from(data: Vec<T>) -> Self {
259 Self { data }
260 }
261}
262
263impl<T> From<Collection<T>> for Vec<T> {
264 fn from(collection: Collection<T>) -> Self {
265 collection.data
266 }
267}
268
269impl<T> std::ops::Index<usize> for Collection<T> {
270 type Output = T;
271
272 fn index(&self, index: usize) -> &Self::Output {
273 &self.data[index]
274 }
275}
276
277impl<T> std::ops::IndexMut<usize> for Collection<T> {
278 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
279 &mut self.data[index]
280 }
281}
282
283impl<T> IntoIterator for Collection<T> {
284 type Item = T;
285 type IntoIter = std::vec::IntoIter<T>;
286
287 fn into_iter(self) -> Self::IntoIter {
288 self.data.into_iter()
289 }
290}
291
292impl<'a, T> IntoIterator for &'a Collection<T> {
293 type Item = &'a T;
294 type IntoIter = std::slice::Iter<'a, T>;
295
296 fn into_iter(self) -> Self::IntoIter {
297 self.data.iter()
298 }
299}
300
301impl<'a, T> IntoIterator for &'a mut Collection<T> {
302 type Item = &'a mut T;
303 type IntoIter = std::slice::IterMut<'a, T>;
304
305 fn into_iter(self) -> Self::IntoIter {
306 self.data.iter_mut()
307 }
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313
314 #[test]
315 fn test_collection_creation() {
316 let collection = Collection::new(vec![1, 2, 3]);
317 assert_eq!(collection.len(), 3);
318 assert!(!collection.is_empty());
319 }
320
321 #[test]
322 fn test_empty_collection() {
323 let collection: Collection<i32> = Collection::empty();
324 assert_eq!(collection.len(), 0);
325 assert!(collection.is_empty());
326 }
327
328 #[test]
329 fn test_get() {
330 let collection = Collection::new(vec![1, 2, 3]);
331 assert_eq!(collection.get(1), Some(&2));
332 assert_eq!(collection.get(5), None);
333 }
334
335 #[test]
336 fn test_first_last() {
337 let collection = Collection::new(vec![1, 2, 3]);
338 assert_eq!(collection.first(), Some(&1));
339 assert_eq!(collection.last(), Some(&3));
340 }
341
342 #[test]
343 fn test_indexing() {
344 let collection = Collection::new(vec![1, 2, 3]);
345 assert_eq!(collection[1], 2);
346 }
347
348 #[test]
349 fn test_into_iter() {
350 let collection = Collection::new(vec![1, 2, 3]);
351 let sum: i32 = collection.into_iter().sum();
352 assert_eq!(sum, 6);
353 }
354
355 #[test]
356 fn test_iter() {
357 let collection = Collection::new(vec![1, 2, 3]);
358 let sum: i32 = collection.iter().sum();
359 assert_eq!(sum, 6);
360 }
361}