ez_err/
slice_ext.rs

1//! Slice extensions that integrate well with the error handling system.
2
3use crate::core::*;
4use crate::flc;
5use std::ops;
6
7/// Extension trait for slices.
8pub trait SliceExt<I, O>
9where
10    O: ?Sized,
11{
12    /// Returns a reference to an element or subslice depending on the type of
13    /// index.
14    ///
15    /// - If given a position, returns a reference to the element at that
16    ///   position or [`Err(_)`] if out of bounds.
17    /// - If given a range, returns the subslice corresponding to that range,
18    ///   or [`Err(_)`] if out of bounds.
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// # use ez_err::prelude::*;
24    /// let v = [10, 40, 30];
25    /// assert_eq!(Ok(&40), v.eget(1));
26    /// assert_eq!(Ok(&[10, 40][..]), v.eget(0..2));
27    /// assert_eq!(&ErrorType::IndexOutOfBounds(3, 3), v.eget(3).err().unwrap().ty());
28    /// assert_eq!(&ErrorType::RangeOutOfBounds(0, 4, 3), v.eget(0..4).err().unwrap().ty());
29    /// ```
30    fn eget(&self, index: I) -> Result<&O>;
31}
32
33/// Mutable version of [`SliceExt`].
34pub trait SliceExtMut<I, O>
35where
36    O: ?Sized,
37{
38    /// Returns a mutable reference to an element or subslice depending on the
39    /// type of index (see [`eget`]) or [`Err(_)`] if the index is out of bounds.
40    ///
41    /// [`eget`]: SliceExt::eget
42    ///
43    /// # Examples
44    ///
45    /// ```
46    /// # use ez_err::prelude::*;
47    /// let x = &mut [0, 1, 2];
48    ///
49    /// if let Ok(elem) = x.eget_mut(1) {
50    ///     *elem = 42;
51    /// }
52    /// assert_eq!(x, &[0, 42, 2]);
53    /// ```
54    fn eget_mut(&mut self, index: I) -> Result<&mut O>;
55}
56
57impl<T> SliceExt<usize, T> for [T] {
58    #[inline]
59    fn eget(&self, index: usize) -> Result<&T> {
60        if index < self.len() {
61            Ok(unsafe { self.get_unchecked(index) })
62        } else {
63            Err(EzError::new(ErrorType::IndexOutOfBounds(index, self.len()))).loc(flc!())
64        }
65    }
66}
67
68impl<'a, T> SliceExt<usize, T> for &'a [T] {
69    #[inline]
70    fn eget(&self, index: usize) -> Result<&T> {
71        if index < self.len() {
72            Ok(unsafe { self.get_unchecked(index) })
73        } else {
74            Err(EzError::new(ErrorType::IndexOutOfBounds(index, self.len()))).loc(flc!())
75        }
76    }
77}
78
79impl<T> SliceExtMut<usize, T> for [T] {
80    #[inline]
81    fn eget_mut(&mut self, index: usize) -> Result<&mut T> {
82        if index < self.len() {
83            Ok(unsafe { self.get_unchecked_mut(index) })
84        } else {
85            Err(EzError::new(ErrorType::IndexOutOfBounds(index, self.len()))).loc(flc!())
86        }
87    }
88}
89
90impl<'a, T> SliceExtMut<usize, T> for &'a mut [T] {
91    #[inline]
92    fn eget_mut(&mut self, index: usize) -> Result<&mut T> {
93        if index < self.len() {
94            Ok(unsafe { self.get_unchecked_mut(index) })
95        } else {
96            Err(EzError::new(ErrorType::IndexOutOfBounds(index, self.len()))).loc(flc!())
97        }
98    }
99}
100
101impl<T> SliceExt<ops::Range<usize>, [T]> for [T] {
102    #[inline]
103    fn eget(&self, index: ops::Range<usize>) -> Result<&[T]> {
104        if index.start > index.end {
105            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
106        } else if index.start >= self.len() || index.end > self.len() {
107            Err(EzError::new(ErrorType::RangeOutOfBounds(
108                index.start,
109                index.end,
110                self.len(),
111            )))
112            .loc(flc!())
113        } else {
114            Ok(unsafe { self.get_unchecked(index) })
115        }
116    }
117}
118
119impl<'a, T> SliceExt<ops::Range<usize>, [T]> for &'a [T] {
120    #[inline]
121    fn eget(&self, index: ops::Range<usize>) -> Result<&[T]> {
122        if index.start > index.end {
123            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
124        } else if index.start >= self.len() || index.end > self.len() {
125            Err(EzError::new(ErrorType::RangeOutOfBounds(
126                index.start,
127                index.end,
128                self.len(),
129            )))
130            .loc(flc!())
131        } else {
132            Ok(unsafe { self.get_unchecked(index) })
133        }
134    }
135}
136
137impl<T> SliceExtMut<ops::Range<usize>, [T]> for [T] {
138    #[inline]
139    fn eget_mut(&mut self, index: ops::Range<usize>) -> Result<&mut [T]> {
140        if index.start > index.end {
141            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
142        } else if index.start >= self.len() || index.end > self.len() {
143            Err(EzError::new(ErrorType::RangeOutOfBounds(
144                index.start,
145                index.end,
146                self.len(),
147            )))
148            .loc(flc!())
149        } else {
150            Ok(unsafe { self.get_unchecked_mut(index) })
151        }
152    }
153}
154
155impl<'a, T> SliceExtMut<ops::Range<usize>, [T]> for &'a mut [T] {
156    #[inline]
157    fn eget_mut(&mut self, index: ops::Range<usize>) -> Result<&mut [T]> {
158        if index.start > index.end {
159            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
160        } else if index.start >= self.len() || index.end > self.len() {
161            Err(EzError::new(ErrorType::RangeOutOfBounds(
162                index.start,
163                index.end,
164                self.len(),
165            )))
166            .loc(flc!())
167        } else {
168            Ok(unsafe { self.get_unchecked_mut(index) })
169        }
170    }
171}
172
173impl<T> SliceExt<ops::RangeTo<usize>, [T]> for [T] {
174    #[inline]
175    fn eget(&self, index: ops::RangeTo<usize>) -> Result<&[T]> {
176        self.eget(0..index.end).loc(flc!())
177    }
178}
179
180impl<'a, T> SliceExt<ops::RangeTo<usize>, [T]> for &'a [T] {
181    #[inline]
182    fn eget(&self, index: ops::RangeTo<usize>) -> Result<&[T]> {
183        self.eget(0..index.end).loc(flc!())
184    }
185}
186
187impl<T> SliceExtMut<ops::RangeTo<usize>, [T]> for [T] {
188    #[inline]
189    fn eget_mut(&mut self, index: ops::RangeTo<usize>) -> Result<&mut [T]> {
190        self.eget_mut(0..index.end).loc(flc!())
191    }
192}
193
194impl<'a, T> SliceExtMut<ops::RangeTo<usize>, [T]> for &'a mut [T] {
195    #[inline]
196    fn eget_mut(&mut self, index: ops::RangeTo<usize>) -> Result<&mut [T]> {
197        self.eget_mut(0..index.end).loc(flc!())
198    }
199}
200
201impl<T> SliceExt<ops::RangeFrom<usize>, [T]> for [T] {
202    #[inline]
203    fn eget(&self, index: ops::RangeFrom<usize>) -> Result<&[T]> {
204        self.eget(index.start..self.len()).loc(flc!())
205    }
206}
207
208impl<'a, T> SliceExt<ops::RangeFrom<usize>, [T]> for &'a [T] {
209    #[inline]
210    fn eget(&self, index: ops::RangeFrom<usize>) -> Result<&[T]> {
211        self.eget(index.start..self.len()).loc(flc!())
212    }
213}
214
215impl<T> SliceExtMut<ops::RangeFrom<usize>, [T]> for [T] {
216    #[inline]
217    fn eget_mut(&mut self, index: ops::RangeFrom<usize>) -> Result<&mut [T]> {
218        self.eget_mut(index.start..self.len()).loc(flc!())
219    }
220}
221
222impl<'a, T> SliceExtMut<ops::RangeFrom<usize>, [T]> for &'a mut [T] {
223    #[inline]
224    fn eget_mut(&mut self, index: ops::RangeFrom<usize>) -> Result<&mut [T]> {
225        self.eget_mut(index.start..self.len()).loc(flc!())
226    }
227}
228
229impl<T> SliceExt<ops::RangeFull, [T]> for [T] {
230    #[inline]
231    fn eget(&self, _: ops::RangeFull) -> Result<&[T]> {
232        Ok(self)
233    }
234}
235
236impl<'a, T> SliceExt<ops::RangeFull, [T]> for &'a [T] {
237    #[inline]
238    fn eget(&self, _: ops::RangeFull) -> Result<&[T]> {
239        Ok(self)
240    }
241}
242
243impl<T> SliceExtMut<ops::RangeFull, [T]> for [T] {
244    #[inline]
245    fn eget_mut(&mut self, _: ops::RangeFull) -> Result<&mut [T]> {
246        Ok(self)
247    }
248}
249
250impl<'a, T> SliceExtMut<ops::RangeFull, [T]> for &'a mut [T] {
251    #[inline]
252    fn eget_mut(&mut self, _: ops::RangeFull) -> Result<&mut [T]> {
253        Ok(self)
254    }
255}
256
257impl<T> SliceExt<ops::RangeInclusive<usize>, [T]> for [T] {
258    #[inline]
259    fn eget(&self, index: ops::RangeInclusive<usize>) -> Result<&[T]> {
260        if *index.end() == usize::MAX {
261            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
262        } else {
263            self.eget(*index.start()..(*index.end() + 1))
264        }
265    }
266}
267
268impl<'a, T> SliceExt<ops::RangeInclusive<usize>, [T]> for &'a [T] {
269    #[inline]
270    fn eget(&self, index: ops::RangeInclusive<usize>) -> Result<&[T]> {
271        if *index.end() == usize::MAX {
272            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
273        } else {
274            self.eget(*index.start()..(*index.end() + 1))
275        }
276    }
277}
278
279impl<T> SliceExtMut<ops::RangeInclusive<usize>, [T]> for [T] {
280    #[inline]
281    fn eget_mut(&mut self, index: ops::RangeInclusive<usize>) -> Result<&mut [T]> {
282        if *index.end() == usize::MAX {
283            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
284        } else {
285            self.eget_mut(*index.start()..(*index.end() + 1))
286        }
287    }
288}
289
290impl<'a, T> SliceExtMut<ops::RangeInclusive<usize>, [T]> for &'a mut [T] {
291    #[inline]
292    fn eget_mut(&mut self, index: ops::RangeInclusive<usize>) -> Result<&mut [T]> {
293        if *index.end() == usize::MAX {
294            Err(EzError::new(ErrorType::InvalidRange)).loc(flc!())
295        } else {
296            self.eget_mut(*index.start()..(*index.end() + 1))
297        }
298    }
299}
300
301impl<T> SliceExt<ops::RangeToInclusive<usize>, [T]> for [T] {
302    #[inline]
303    fn eget(&self, index: ops::RangeToInclusive<usize>) -> Result<&[T]> {
304        self.eget(0..=index.end).loc(flc!())
305    }
306}
307
308impl<'a, T> SliceExt<ops::RangeToInclusive<usize>, [T]> for &'a [T] {
309    #[inline]
310    fn eget(&self, index: ops::RangeToInclusive<usize>) -> Result<&[T]> {
311        self.eget(0..=index.end).loc(flc!())
312    }
313}
314
315impl<T> SliceExtMut<ops::RangeToInclusive<usize>, [T]> for [T] {
316    #[inline]
317    fn eget_mut(&mut self, index: ops::RangeToInclusive<usize>) -> Result<&mut [T]> {
318        self.eget_mut(0..=index.end).loc(flc!())
319    }
320}
321
322impl<'a, T> SliceExtMut<ops::RangeToInclusive<usize>, [T]> for &'a mut [T] {
323    #[inline]
324    fn eget_mut(&mut self, index: ops::RangeToInclusive<usize>) -> Result<&mut [T]> {
325        self.eget_mut(0..=index.end).loc(flc!())
326    }
327}
328
329#[cfg(test)]
330mod tests {
331    use super::*;
332
333    #[test]
334    fn plain_index() {
335        let arr = [6, 12, 5];
336
337        assert_eq!(Ok(&6), arr.eget(0));
338        assert_eq!(Ok(&12), arr.eget(1));
339        assert_eq!(Ok(&5), arr.eget(2));
340        assert!(arr.eget(3).is_err());
341    }
342
343    #[test]
344    fn plain_index_ref() {
345        let arr = &[6, 12, 5];
346
347        assert_eq!(Ok(&6), arr.eget(0));
348        assert_eq!(Ok(&12), arr.eget(1));
349        assert_eq!(Ok(&5), arr.eget(2));
350        assert!(arr.eget(3).is_err());
351    }
352
353    #[test]
354    fn plain_index_mut() {
355        let arr = &mut [6, 12, 5];
356
357        assert_eq!(Ok(&mut 6), arr.eget_mut(0));
358        assert_eq!(Ok(&mut 12), arr.eget_mut(1));
359        assert_eq!(Ok(&mut 5), arr.eget_mut(2));
360        assert!(arr.eget_mut(3).is_err());
361    }
362
363    #[test]
364    fn range() {
365        let arr = [6, 12, 5];
366
367        assert_eq!(Ok(&arr[0..2]), arr.eget(0..2));
368        assert_eq!(Ok(&arr[1..3]), arr.eget(1..3));
369        assert!(arr.eget(1..4).is_err());
370    }
371
372    #[test]
373    fn range_ref() {
374        let arr = &[6, 12, 5];
375
376        assert_eq!(Ok(&arr[0..2]), arr.eget(0..2));
377        assert_eq!(Ok(&arr[1..3]), arr.eget(1..3));
378        assert!(arr.eget(1..4).is_err());
379    }
380
381    #[test]
382    fn range_mut() {
383        let arr = &mut [6, 12, 5];
384        let clone = &mut [6, 12, 5];
385
386        assert_eq!(Ok(&mut clone[0..2]), arr.eget_mut(0..2));
387        assert_eq!(Ok(&mut clone[1..3]), arr.eget_mut(1..3));
388        assert!(arr.eget_mut(1..4).is_err());
389    }
390
391    #[test]
392    fn range_to() {
393        let arr = [6, 12, 5];
394
395        assert_eq!(Ok(&arr[..2]), arr.eget(..2));
396        assert_eq!(Ok(&arr[..3]), arr.eget(..3));
397        assert!(arr.eget(..4).is_err());
398    }
399
400    #[test]
401    fn range_to_ref() {
402        let arr = &[6, 12, 5];
403
404        assert_eq!(Ok(&arr[..2]), arr.eget(..2));
405        assert_eq!(Ok(&arr[..3]), arr.eget(..3));
406        assert!(arr.eget(..4).is_err());
407    }
408
409    #[test]
410    fn range_to_mut() {
411        let arr = &mut [6, 12, 5];
412        let clone = &mut [6, 12, 5];
413
414        assert_eq!(Ok(&mut clone[..2]), arr.eget_mut(..2));
415        assert_eq!(Ok(&mut clone[..3]), arr.eget_mut(..3));
416        assert!(arr.eget_mut(..4).is_err());
417    }
418
419    #[test]
420    fn range_from() {
421        let arr = [6, 12, 5];
422
423        assert_eq!(Ok(&arr[1..]), arr.eget(1..));
424        assert_eq!(Ok(&arr[2..]), arr.eget(2..));
425        assert!(arr.eget(3..).is_err());
426    }
427
428    #[test]
429    fn range_from_ref() {
430        let arr = &[6, 12, 5];
431
432        assert_eq!(Ok(&arr[1..]), arr.eget(1..));
433        assert_eq!(Ok(&arr[2..]), arr.eget(2..));
434        assert!(arr.eget(3..).is_err());
435    }
436
437    #[test]
438    fn range_from_mut() {
439        let arr = &mut [6, 12, 5];
440        let clone = &mut [6, 12, 5];
441
442        assert_eq!(Ok(&mut clone[1..]), arr.eget_mut(1..));
443        assert_eq!(Ok(&mut clone[2..]), arr.eget_mut(2..));
444        assert!(arr.eget_mut(3..).is_err());
445    }
446
447    #[test]
448    fn range_full() {
449        let arr = [6, 12, 5];
450
451        assert_eq!(Ok(&arr[..]), arr.eget(..));
452    }
453
454    #[test]
455    fn range_full_ref() {
456        let arr = &[6, 12, 5];
457
458        assert_eq!(Ok(&arr[..]), arr.eget(..));
459    }
460
461    #[test]
462    fn range_full_mut() {
463        let arr = &mut [6, 12, 5];
464        let clone = &mut [6, 12, 5];
465
466        assert_eq!(Ok(&mut clone[..]), arr.eget_mut(..));
467    }
468
469    #[test]
470    fn range_inclusive() {
471        let arr = [6, 12, 5];
472
473        assert_eq!(Ok(&arr[0..=1]), arr.eget(0..=1));
474        assert_eq!(Ok(&arr[1..=2]), arr.eget(1..=2));
475        assert!(arr.eget(1..=3).is_err());
476    }
477
478    #[test]
479    fn range_inclusive_ref() {
480        let arr = &[6, 12, 5];
481
482        assert_eq!(Ok(&arr[0..=1]), arr.eget(0..=1));
483        assert_eq!(Ok(&arr[1..=2]), arr.eget(1..=2));
484        assert!(arr.eget(1..=3).is_err());
485    }
486
487    #[test]
488    fn range_inclusive_mut() {
489        let arr = &mut [6, 12, 5];
490        let clone = &mut [6, 12, 5];
491
492        assert_eq!(Ok(&mut clone[0..=1]), arr.eget_mut(0..=1));
493        assert_eq!(Ok(&mut clone[1..=2]), arr.eget_mut(1..=2));
494        assert!(arr.eget_mut(1..=3).is_err());
495    }
496
497    #[test]
498    fn range_to_inclusive() {
499        let arr = [6, 12, 5];
500
501        assert_eq!(Ok(&arr[..=1]), arr.eget(..=1));
502        assert_eq!(Ok(&arr[..=2]), arr.eget(..=2));
503        assert!(arr.eget(..=3).is_err());
504    }
505
506    #[test]
507    fn range_to_inclusive_ref() {
508        let arr = &[6, 12, 5];
509
510        assert_eq!(Ok(&arr[..=1]), arr.eget(..=1));
511        assert_eq!(Ok(&arr[..=2]), arr.eget(..=2));
512        assert!(arr.eget(..=3).is_err());
513    }
514
515    #[test]
516    fn range_to_inclusive_mut() {
517        let arr = &mut [6, 12, 5];
518        let clone = &mut [6, 12, 5];
519
520        assert_eq!(Ok(&mut clone[..=1]), arr.eget_mut(..=1));
521        assert_eq!(Ok(&mut clone[..=2]), arr.eget_mut(..=2));
522        assert!(arr.eget_mut(..=3).is_err());
523    }
524}