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}