ps_util/array.rs
1use std::fmt::Write;
2
3use crate::{subarray, subarray_checked, subarray_unchecked};
4
5pub trait Array<T> {
6 /// Returns a reference to the element at the specified index,
7 /// or `None` if the index is out of bounds.
8 ///
9 /// # Examples
10 ///
11 /// ```
12 /// use ps_util::Array;
13 /// let arr = [1, 2, 3];
14 /// assert_eq!(arr.at(0), Some(&1));
15 /// assert_eq!(arr.at(5), None);
16 /// ```
17 fn at(&self, index: usize) -> Option<&T>;
18
19 /// Concatenates this array with another slice and returns a new vector.
20 ///
21 /// # Examples
22 ///
23 /// ```
24 /// use ps_util::Array;
25 /// let arr = [1, 2];
26 /// let result = arr.concat(&[3, 4]);
27 /// assert_eq!(result, vec![1, 2, 3, 4]);
28 /// ```
29 fn concat(&self, other: impl AsRef<[T]>) -> Vec<T>
30 where
31 T: Clone;
32
33 /// Returns an iterator of (index, &T) tuples for each element.
34 ///
35 /// # Examples
36 ///
37 /// ```
38 /// use ps_util::Array;
39 /// let arr = ['a', 'b'];
40 /// let entries: Vec<_> = arr.entries().collect();
41 /// assert_eq!(entries, vec![(0, &'a'), (1, &'b')]);
42 /// ```
43 fn entries<'a>(&'a self) -> impl Iterator<Item = (usize, &'a T)>
44 where
45 T: 'a;
46
47 /// Tests whether all elements match the predicate.
48 ///
49 /// Returns `true` if the predicate returns `true` for every element,
50 /// or if the array is empty.
51 ///
52 /// # Examples
53 ///
54 /// ```
55 /// use ps_util::Array;
56 /// let arr = [2, 4, 6];
57 /// assert!(arr.every(|x| x % 2 == 0));
58 /// assert!(!arr.every(|x| x > &5));
59 /// ```
60 fn every(&self, predicate: impl FnMut(&T) -> bool) -> bool;
61
62 /// Returns a reference to the first element that matches the predicate.
63 ///
64 /// # Examples
65 ///
66 /// ```
67 /// use ps_util::Array;
68 /// let arr = [1, 2, 3, 4];
69 /// assert_eq!(arr.find(|x| x > &2), Some(&3));
70 /// assert_eq!(arr.find(|x| x > &10), None);
71 /// ```
72 fn find(&self, predicate: impl FnMut(&T) -> bool) -> Option<&T>;
73
74 /// Returns the index of the first element that matches the predicate.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use ps_util::Array;
80 /// let arr = [1, 2, 3, 4];
81 /// assert_eq!(arr.find_index(|x| x > &2), Some(2));
82 /// assert_eq!(arr.find_index(|x| x > &10), None);
83 /// ```
84 fn find_index(&self, predicate: impl FnMut(&T) -> bool) -> Option<usize>;
85
86 /// Returns a reference to the last element that matches the predicate.
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// use ps_util::Array;
92 /// let arr = [1, 2, 3, 4];
93 /// assert_eq!(arr.find_last(|x| x < &4), Some(&3));
94 /// assert_eq!(arr.find_last(|x| x > &10), None);
95 /// ```
96 fn find_last(&self, predicate: impl FnMut(&T) -> bool) -> Option<&T>;
97
98 /// Returns the index of the last element that matches the predicate.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use ps_util::Array;
104 /// let arr = [1, 2, 3, 4];
105 /// assert_eq!(arr.find_last_index(|x| x < &4), Some(2));
106 /// assert_eq!(arr.find_last_index(|x| x > &10), None);
107 /// ```
108 fn find_last_index(&self, predicate: impl FnMut(&T) -> bool) -> Option<usize>;
109
110 /// Returns a vector containing all elements that match the predicate.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use ps_util::Array;
116 /// let arr = [1, 2, 3, 4];
117 /// assert_eq!(arr.filter(|x| x % 2 == 0), vec![2, 4]);
118 /// ```
119 fn filter(&self, predicate: impl FnMut(&T) -> bool) -> Vec<T>
120 where
121 T: Clone;
122
123 /// Flattens a level of nesting in an array of iterables.
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// use ps_util::Array;
129 /// let arr = [vec![1, 2], vec![3, 4]];
130 /// assert_eq!(arr.flat(), vec![1, 2, 3, 4]);
131 /// ```
132 fn flat(&self) -> Vec<T::Item>
133 where
134 T: Clone + IntoIterator;
135
136 /// Maps each element to an iterable and flattens the result.
137 ///
138 /// # Examples
139 ///
140 /// ```
141 /// use ps_util::Array;
142 /// let arr = [1, 2, 3];
143 /// let result = arr.flat_map(|x| vec![*x, *x * 2]);
144 /// assert_eq!(result, vec![1, 2, 2, 4, 3, 6]);
145 /// ```
146 fn flat_map<O, I>(&self, mapper: impl FnMut(&T) -> I) -> Vec<O>
147 where
148 I: IntoIterator<Item = O>;
149
150 /// Applies a closure to each element for side effects.
151 ///
152 /// # Examples
153 ///
154 /// ```
155 /// use ps_util::Array;
156 /// let arr = [1, 2, 3];
157 /// arr.for_each(|x| println!("{}", x));
158 /// ```
159 fn for_each(&self, cb: impl FnMut(&T));
160
161 /// Checks whether the array contains the specified value.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// use ps_util::Array;
167 /// let arr = [1, 2, 3];
168 /// assert!(arr.includes(&2));
169 /// assert!(!arr.includes(&5));
170 /// ```
171 fn includes(&self, value: &T) -> bool
172 where
173 T: PartialEq;
174
175 /// Returns the index of the first occurrence of the specified value,
176 /// or `None` if not found.
177 ///
178 /// # Examples
179 ///
180 /// ```
181 /// use ps_util::Array;
182 /// let arr = [1, 2, 3, 2];
183 /// assert_eq!(arr.index_of(&2), Some(1));
184 /// assert_eq!(arr.index_of(&5), None);
185 /// ```
186 fn index_of(&self, value: &T) -> Option<usize>
187 where
188 T: PartialEq;
189
190 /// Returns `true` if the array is empty.
191 ///
192 /// # Examples
193 ///
194 /// ```
195 /// use ps_util::Array;
196 /// assert!(Vec::<i32>::new().is_empty());
197 /// assert!(![1].is_empty());
198 /// ```
199 fn is_empty(&self) -> bool;
200
201 /// Concatenates all elements into a string, separated by the given separator.
202 ///
203 /// # Errors
204 ///
205 /// Errors are passed from the [`std::fmt::Display`] implementation.
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use ps_util::Array;
211 /// let arr = [1, 2, 3];
212 /// assert_eq!(arr.join(", ").unwrap(), "1, 2, 3");
213 /// ```
214 fn join(&self, separator: &str) -> Result<String, std::fmt::Error>
215 where
216 T: std::fmt::Display;
217
218 /// Returns an iterator of indices (0, 1, 2, ...).
219 ///
220 /// # Examples
221 ///
222 /// ```
223 /// use ps_util::Array;
224 /// let arr = ['a', 'b', 'c'];
225 /// let keys: Vec<_> = arr.keys().collect();
226 /// assert_eq!(keys, vec![0, 1, 2]);
227 /// ```
228 fn keys(&self) -> impl Iterator<Item = usize>;
229
230 /// Returns the index of the last occurrence of the specified value,
231 /// or `None` if not found.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// use ps_util::Array;
237 /// let arr = [1, 2, 3, 2];
238 /// assert_eq!(arr.last_index_of(&2), Some(3));
239 /// assert_eq!(arr.last_index_of(&5), None);
240 /// ```
241 fn last_index_of(&self, value: &T) -> Option<usize>
242 where
243 T: PartialEq;
244
245 /// Returns the number of elements in the array.
246 ///
247 /// # Examples
248 ///
249 /// ```
250 /// use ps_util::Array;
251 /// let arr = [1, 2, 3];
252 /// assert_eq!(arr.len(), 3);
253 /// ```
254 fn len(&self) -> usize;
255
256 /// Transforms each element using the provided mapper function
257 /// and returns a vector of the results.
258 ///
259 /// # Examples
260 ///
261 /// ```
262 /// use ps_util::Array;
263 /// let arr = [1, 2, 3u8];
264 /// assert_eq!(arr.as_slice().map(|x| x * 2), vec![2, 4, 6]);
265 /// ```
266 fn map<O>(&self, mapper: impl FnMut(&T) -> O) -> Vec<O>;
267
268 /// Reduces the array to a single value by applying a callback
269 /// with an accumulator, starting from the left.
270 ///
271 /// # Examples
272 ///
273 /// ```
274 /// use ps_util::Array;
275 /// let arr = [1, 2, 3, 4];
276 /// let sum = arr.reduce(|acc, x| acc + x, 0);
277 /// assert_eq!(sum, 10);
278 /// ```
279 fn reduce<O>(&self, reducer: impl FnMut(O, &T) -> O, initial: O) -> O;
280
281 /// Reduces the array to a single value by applying a callback
282 /// with an accumulator, starting from the right.
283 ///
284 /// # Examples
285 ///
286 /// ```
287 /// use ps_util::Array;
288 /// let arr = [1, 2, 3];
289 /// let result = arr.reduce_right(
290 /// |acc, x| format!("{}{}", acc, x),
291 /// String::new()
292 /// );
293 /// assert_eq!(result, "321");
294 /// ```
295 fn reduce_right<O>(&self, reducer: impl FnMut(O, &T) -> O, initial: O) -> O;
296
297 /// Returns a slice of the array from `start` to `end` (exclusive).
298 ///
299 /// If `end` is `None`, slices to the end of the array. Indices are clamped
300 /// to valid bounds; if `start` exceeds the array length, an empty slice
301 /// is returned.
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// use ps_util::Array;
307 /// let arr = [1, 2, 3, 4];
308 /// assert_eq!(arr.slice(1, Some(3)), &[2, 3][..]);
309 /// assert_eq!(arr.slice(2, None), &[3, 4][..]);
310 /// assert_eq!(arr.slice(10, Some(20)), &[][..]);
311 /// ```
312 fn slice(&self, start: usize, end: Option<usize>) -> &[T];
313
314 /// Tests whether any element matches the predicate.
315 ///
316 /// Returns `true` if the predicate returns `true` for at least one element.
317 ///
318 /// # Examples
319 ///
320 /// ```
321 /// use ps_util::Array;
322 /// let arr = [1, 2, 3];
323 /// assert!(arr.some(|x| x > &2));
324 /// assert!(!arr.some(|x| x > &10));
325 /// ```
326 fn some(&self, predicate: impl FnMut(&T) -> bool) -> bool;
327
328 /// Returns a fixed-size array reference starting at the given index.
329 ///
330 /// # Panics
331 ///
332 /// Panics if there are not enough elements remaining in the array.
333 ///
334 /// # Examples
335 ///
336 /// ```
337 /// use ps_util::Array;
338 /// let arr = [1, 2, 3, 4];
339 /// assert_eq!(arr.subarray::<2>(1), &[2, 3]);
340 /// ```
341 fn subarray<const S: usize>(&self, index: usize) -> &[T; S];
342
343 /// Checked version of `subarray`. Returns `None` if bounds are exceeded.
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// use ps_util::Array;
349 /// let arr = [1, 2, 3];
350 /// assert_eq!(arr.subarray_checked::<2>(1), Some(&[2, 3]));
351 /// assert_eq!(arr.subarray_checked::<2>(2), None);
352 /// ```
353 fn subarray_checked<const S: usize>(&self, index: usize) -> Option<&[T; S]>;
354
355 /// Unchecked version of `subarray`. Undefined behavior if bounds are exceeded.
356 ///
357 /// # Safety
358 ///
359 /// Caller must ensure that `index + S <= self.len()`.
360 ///
361 /// # Examples
362 ///
363 /// ```
364 /// use ps_util::Array;
365 /// let arr = [1, 2, 3, 4];
366 /// unsafe {
367 /// assert_eq!(arr.subarray_unchecked::<2>(1), &[2, 3]);
368 /// }
369 /// ```
370 unsafe fn subarray_unchecked<const S: usize>(&self, index: usize) -> &[T; S];
371
372 /// Returns an iterator over references to the elements.
373 ///
374 /// # Examples
375 ///
376 /// ```
377 /// use ps_util::Array;
378 /// let arr = [1, 2, 3];
379 /// let values: Vec<_> = arr.values().collect();
380 /// assert_eq!(values, vec![&1, &2, &3]);
381 /// ```
382 fn values<'a>(&'a self) -> impl Iterator<Item = &'a T>
383 where
384 T: 'a;
385}
386
387impl<A, T> Array<T> for A
388where
389 A: AsRef<[T]>,
390{
391 fn at(&self, index: usize) -> Option<&T> {
392 self.as_ref().get(index)
393 }
394
395 fn concat(&self, other: impl AsRef<[T]>) -> Vec<T>
396 where
397 T: Clone,
398 {
399 let lhs = self.as_ref();
400 let rhs = other.as_ref();
401
402 let mut concatenated = Vec::with_capacity(lhs.len() + rhs.len());
403
404 concatenated.extend_from_slice(lhs);
405 concatenated.extend_from_slice(rhs);
406
407 concatenated
408 }
409
410 fn entries<'a>(&'a self) -> impl Iterator<Item = (usize, &'a T)>
411 where
412 T: 'a,
413 {
414 self.as_ref().iter().enumerate()
415 }
416
417 fn every(&self, predicate: impl FnMut(&T) -> bool) -> bool {
418 self.as_ref().iter().all(predicate)
419 }
420
421 fn filter(&self, mut predicate: impl FnMut(&T) -> bool) -> Vec<T>
422 where
423 T: Clone,
424 {
425 self.as_ref()
426 .iter()
427 .filter(|item| predicate(item))
428 .cloned()
429 .collect()
430 }
431
432 fn find(&self, mut predicate: impl FnMut(&T) -> bool) -> Option<&T> {
433 Iterator::find(&mut self.as_ref().iter(), |item| predicate(item))
434 }
435
436 fn find_index(&self, predicate: impl FnMut(&T) -> bool) -> Option<usize> {
437 self.as_ref().iter().position(predicate)
438 }
439
440 fn find_last(&self, mut predicate: impl FnMut(&T) -> bool) -> Option<&T> {
441 self.as_ref().iter().rfind(|item| predicate(item))
442 }
443
444 fn find_last_index(&self, predicate: impl FnMut(&T) -> bool) -> Option<usize> {
445 self.as_ref().iter().rposition(predicate)
446 }
447
448 fn flat(&self) -> Vec<<T>::Item>
449 where
450 T: Clone + IntoIterator,
451 {
452 self.as_ref().iter().cloned().flatten().collect()
453 }
454
455 fn flat_map<O, I>(&self, mapper: impl FnMut(&T) -> I) -> Vec<O>
456 where
457 I: IntoIterator<Item = O>,
458 {
459 self.as_ref().iter().flat_map(mapper).collect()
460 }
461
462 fn for_each(&self, cb: impl FnMut(&T)) {
463 self.as_ref().iter().for_each(cb);
464 }
465
466 fn includes(&self, value: &T) -> bool
467 where
468 T: PartialEq,
469 {
470 self.as_ref().contains(value)
471 }
472
473 fn index_of(&self, value: &T) -> Option<usize>
474 where
475 T: PartialEq,
476 {
477 self.as_ref().iter().position(|x| x == value)
478 }
479
480 fn is_empty(&self) -> bool {
481 self.as_ref().is_empty()
482 }
483
484 fn join(&self, separator: &str) -> Result<String, std::fmt::Error>
485 where
486 T: std::fmt::Display,
487 {
488 let mut a = String::new();
489 let mut iterator = self.as_ref().iter();
490
491 if let Some(first) = iterator.next() {
492 write!(&mut a, "{first}")?;
493
494 for item in iterator {
495 write!(&mut a, "{separator}{item}")?;
496 }
497 }
498
499 Ok(a)
500 }
501
502 fn keys(&self) -> impl Iterator<Item = usize> {
503 0..self.as_ref().len()
504 }
505
506 fn last_index_of(&self, value: &T) -> Option<usize>
507 where
508 T: PartialEq,
509 {
510 self.find_last_index(|item| item == value)
511 }
512
513 fn len(&self) -> usize {
514 self.as_ref().len()
515 }
516
517 fn map<O>(&self, mapper: impl FnMut(&T) -> O) -> Vec<O> {
518 self.as_ref().iter().map(mapper).collect()
519 }
520
521 fn reduce<O>(&self, reducer: impl FnMut(O, &T) -> O, initial: O) -> O {
522 self.as_ref().iter().fold(initial, reducer)
523 }
524
525 fn reduce_right<O>(&self, reducer: impl FnMut(O, &T) -> O, initial: O) -> O {
526 self.as_ref().iter().rev().fold(initial, reducer)
527 }
528
529 fn slice(&self, start: usize, end: Option<usize>) -> &[T] {
530 let full = self.as_ref();
531 let len = full.len();
532 let start = usize::min(start, len);
533 let end = end.unwrap_or(len).clamp(start, len);
534
535 &full[start..end]
536 }
537
538 fn some(&self, predicate: impl FnMut(&T) -> bool) -> bool {
539 self.as_ref().iter().any(predicate)
540 }
541
542 fn subarray<const S: usize>(&self, index: usize) -> &[T; S] {
543 subarray(self.as_ref(), index)
544 }
545
546 fn subarray_checked<const S: usize>(&self, index: usize) -> Option<&[T; S]> {
547 subarray_checked(self.as_ref(), index)
548 }
549
550 unsafe fn subarray_unchecked<const S: usize>(&self, index: usize) -> &[T; S] {
551 subarray_unchecked(self.as_ref(), index)
552 }
553
554 fn values<'a>(&'a self) -> impl Iterator<Item = &'a T>
555 where
556 T: 'a,
557 {
558 self.as_ref().iter()
559 }
560}