core_extensions/slices/
extensions.rs

1//! Extension trait for \[T\] and [str].
2//!
3//!
4//!
5
6// use ranges::RangeBounds;
7use super::{BiasDirection, SliceBias,SplitSliceWhile,RSplitSliceWhile};
8
9use std_::borrow::Borrow;
10use std_::cmp;
11use std_::mem;
12use std_::ops::Range;
13
14
15/// Extension trait for `[T]`.
16pub trait ValSliceExt: SliceExt + Borrow<[<Self as SliceExt>::Elem]> {
17    /// Returns an iterator over subslices whose elements were mapped 
18    /// to the same value by `mapper`.
19    /// 
20    /// The returned type implements 
21    /// `DoubleEndedIterator<Item =`[`KeySlice`](./struct.KeySlice.html)`<Self::Elem, U>>`.
22    /// 
23    /// # Example
24    /// 
25    /// ```
26    /// use core_extensions::ValSliceExt;
27    /// use core_extensions::slices::KeySlice;
28    /// 
29    /// {
30    ///     let list = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
31    /// 
32    ///     assert_eq!(
33    ///         list.split_while(|x| x/4).collect::<Vec<_>>(),
34    ///         vec![
35    ///             KeySlice{key: 0, slice: &[0, 1, 2, 3]},
36    ///             KeySlice{key: 1, slice: &[4, 5, 6, 7]},
37    ///             KeySlice{key: 2, slice: &[8]},
38    ///         ]
39    ///     );
40    /// }
41    /// 
42    /// {
43    ///     let list = [0, 4, 1, 5, 9, 8, 7];
44    /// 
45    ///     assert_eq!(
46    ///         list.split_while(|x| x%4).collect::<Vec<_>>(),
47    ///         vec![
48    ///             KeySlice{key: 0, slice: &[0, 4]},
49    ///             KeySlice{key: 1, slice: &[1, 5, 9]},
50    ///             KeySlice{key: 0, slice: &[8]},
51    ///             KeySlice{key: 3, slice: &[7]},
52    ///         ]
53    ///     );
54    /// }
55    /// 
56    /// 
57    /// ```
58    /// 
59    fn split_while<'a, P, U>(&'a self, mut mapper: P) -> SplitSliceWhile<'a, Self::Elem, P, U>
60    where
61        P: FnMut(&'a Self::Elem) -> U,
62        U: Eq + Clone,
63    {
64        let this:&'a [Self::Elem] = self.borrow();
65        SplitSliceWhile {
66            last_left: this.first().map(&mut mapper),
67            last_right: this.last().map(&mut mapper),
68            mapper,
69            s: this,
70        }
71    }
72
73    /// A variation of [`split_while`](#method.split_while) that iterates
74    /// from the right(the order of subslices is reversed).
75    /// 
76    /// The returned type implements 
77    /// `DoubleEndedIterator<Item =`[`KeySlice`](./struct.KeySlice.html)`<Self::Elem, U>>`.
78    /// 
79    /// # Example
80    /// 
81    /// ```
82    /// use core_extensions::ValSliceExt;
83    /// use core_extensions::slices::KeySlice;
84    /// 
85    /// {
86    ///     let list = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
87    /// 
88    ///     assert_eq!(
89    ///         list.rsplit_while(|x| x/4 ).collect::<Vec<_>>(),
90    ///         vec![
91    ///             KeySlice{key: 2, slice: &[8]},
92    ///             KeySlice{key: 1, slice: &[4, 5, 6, 7]},
93    ///             KeySlice{key: 0, slice: &[0, 1, 2, 3]},
94    ///         ]
95    ///     );
96    /// }
97    /// 
98    /// {
99    ///     let list = [0, 4, 1, 5, 9, 8, 7];
100    /// 
101    ///     assert_eq!(
102    ///         list.rsplit_while(|x| x%4 ).collect::<Vec<_>>(),
103    ///         vec![
104    ///             KeySlice{key: 3, slice: &[7]},
105    ///             KeySlice{key: 0, slice: &[8]},
106    ///             KeySlice{key: 1, slice: &[1, 5, 9]},
107    ///             KeySlice{key: 0, slice: &[0, 4]},
108    ///         ]
109    ///     );
110    /// }
111    /// 
112    /// 
113    /// 
114    /// ```
115    /// 
116    fn rsplit_while<'a, P, U>(&'a self, mut mapper: P) -> RSplitSliceWhile<'a, Self::Elem, P, U>
117    where
118        P: FnMut(&'a Self::Elem) -> U,
119        U: Eq + Clone,
120    {
121        let this: &'a [Self::Elem] = self.borrow();
122        RSplitSliceWhile {
123            last_left: this.first().map(&mut mapper),
124            last_right: this.last().map(&mut mapper),
125            mapper,
126            s: this,
127        }
128    }
129}
130
131impl<This> ValSliceExt for This
132where
133    This: ?Sized + SliceExt,
134    This: Borrow<[Self::Elem]>,
135{}
136
137
138
139/// Extension trait for `[T]` and `str`.
140pub trait SliceExt {
141    /// The type of a slice element.
142    type Elem;
143
144    /// Checks whether self fully contains the `other` slice in memory.
145    ///
146    /// If `other` is a zero-length slice it is not contained inside `self`.
147    ///
148    /// # Example
149    ///
150    /// ### Called on slices
151    ///
152    /// ```
153    /// use core_extensions::SliceExt;
154    ///
155    /// let list = vec![0, 1, 2, 3, 4, 5];
156    /// 
157    /// let another = [6, 7, 8];
158    /// 
159    /// assert!(list.contains_slice(&list[..1]));
160    /// assert!(list.contains_slice(&list[3..]));
161    ///
162    /// // Empty slices aren't considered contained by any other slice
163    /// assert!(!list.contains_slice(&list[..0]));
164    /// assert!(!list.contains_slice(&another[..0]));
165    ///
166    /// assert!(!list.contains_slice(&another));
167    ///
168    /// ```
169    ///
170    /// ### Called on `str`s
171    ///
172    /// ```
173    /// use core_extensions::SliceExt;
174    ///
175    /// let string = "foo bar baz";
176    /// 
177    /// let another = String::from(string);
178    /// 
179    /// let foo = &string[..3];
180    /// let bar = &string[4..7];
181    /// let baz = &string[8..11];
182    /// 
183    /// assert!(string.contains_slice(foo));
184    /// assert!(string.contains_slice(bar));
185    /// assert!(string.contains_slice(baz));
186    ///
187    /// // Empty slices aren't considered contained by any other slice
188    /// assert!(!string.contains_slice(&string[..0]));
189    ///
190    /// assert!(!string.contains_slice(&another));
191    ///
192    /// ```
193    fn contains_slice(&self, other: &Self) -> bool;
194
195    /// Checks whether `self` is exactly the `other` slice in memory.
196    ///
197    /// # Example
198    ///
199    /// ### Called on slices
200    ///
201    /// ```
202    /// use core_extensions::SliceExt;
203    ///
204    /// let list = [0, 1, 2, 3, 4, 5];
205    /// let slice_0 = &list[..0];
206    /// let slice_1 = &list[..];
207    ///
208    /// let other = [0, 1, 2, 3, 4, 5];
209    ///
210    /// assert!( slice_0.is_slice(slice_0));
211    /// assert!( slice_0.is_slice(&list[..0]));
212    /// assert!(!slice_0.is_slice(slice_1));
213    /// assert!(!slice_0.is_slice(&[]));
214    ///
215    /// assert!(!list.is_slice(&other));
216    ///
217    /// ```
218    ///
219    /// ### Called on `str`s
220    ///
221    /// ```
222    /// use core_extensions::SliceExt;
223    ///
224    /// let string = "foo bar baz";
225    /// 
226    /// let another = String::from(string);
227    /// 
228    /// let foo = &string[..3];
229    /// let bar = &string[4..7];
230    /// let baz = &string[8..11];
231    /// 
232    /// assert!(!string.is_slice(foo));
233    /// assert!(!string.is_slice(bar));
234    /// assert!(!string.is_slice(baz));
235    /// assert!(string.is_slice(string));
236    ///
237    /// assert!(string[..0].is_slice(&string[..0]));
238    ///
239    /// assert!(!string.is_slice(&another));
240    ///
241    /// ```
242    fn is_slice(&self, other: &Self) -> bool;
243
244    /// Returns the index at which `other` starts.
245    ///
246    /// If `other` is not inside `self`, this returns `self.len()`
247    ///
248    /// # Example
249    ///
250    /// ### Called on slices
251    ///
252    /// ```
253    /// use core_extensions::SliceExt;
254    ///
255    /// let list = vec![0, 1, 2, 3, 4, 5];
256    /// 
257    /// let other = [0, 1, 2, 3];
258    ///
259    /// assert_eq!(list.offset_of_slice(&list[..0]), 0);
260    /// assert_eq!(list.offset_of_slice(&list[3..]), 3);
261    /// assert_eq!(list.offset_of_slice(&list[5..]), 5);
262    /// assert_eq!(list.offset_of_slice(&list[6..]), list.len());
263    /// assert_eq!(list.offset_of_slice(&[]), list.len());
264    ///
265    /// assert_eq!(list.offset_of_slice(&other), list.len());
266    ///
267    /// ```
268    ///
269    /// ### Called on `str`s
270    ///
271    /// ```
272    /// use core_extensions::SliceExt;
273    ///
274    /// let string = "foo bar baz";
275    /// 
276    /// let another = String::from(string);
277    /// 
278    /// let foo = &string[..3];
279    /// let bar = &string[4..7];
280    /// let baz = &string[8..11];
281    /// 
282    /// assert_eq!(string.offset_of_slice(string), 0);
283    /// assert_eq!(string.offset_of_slice(&string[..0]), 0);
284    /// assert_eq!(string.offset_of_slice(foo), 0);
285    /// assert_eq!(string.offset_of_slice(bar), 4);
286    /// assert_eq!(string.offset_of_slice(baz), 8);
287    /// assert_eq!(string.offset_of_slice(&string[11..]), 11);
288    ///
289    /// assert_eq!(string.offset_of_slice(&another), string.len());
290    ///
291    /// ```
292    fn offset_of_slice(&self, other: &Self) -> usize;
293
294    /// Returns the index at which `other` starts.
295    ///
296    /// If `other` is a zero-length slice, or is not inside `self`, this returns `None`.
297    ///
298    /// # Example
299    ///
300    /// ### Called on slices
301    ///
302    /// ```
303    /// use core_extensions::SliceExt;
304    ///
305    /// let list = [0, 1, 2, 3, 4, 5];
306    /// 
307    /// let other = [0, 1, 2, 3];
308    ///
309    /// assert_eq!(list.get_offset_of_slice(&list[..0]), None);
310    /// assert_eq!(list.get_offset_of_slice(&list[1..]), Some(1));
311    /// assert_eq!(list.get_offset_of_slice(&list[3..]), Some(3));
312    /// assert_eq!(list.get_offset_of_slice(&list[5..]), Some(5));
313    /// assert_eq!(list.get_offset_of_slice(&list[6..]), None);
314    ///
315    /// assert_eq!(list.get_offset_of_slice(&other), None);
316    ///
317    /// ```
318    ///
319    /// ### Called on `str`s
320    ///
321    /// ```
322    /// use core_extensions::SliceExt;
323    ///
324    /// let string = "foo bar baz";
325    /// 
326    /// let another = String::from(string);
327    /// 
328    /// let foo = &string[..3];
329    /// let bar = &string[4..7];
330    /// let baz = &string[8..11];
331    /// 
332    /// assert_eq!(string.get_offset_of_slice(&string[..0]), None);
333    /// assert_eq!(string.get_offset_of_slice(string), Some(0));
334    /// assert_eq!(string.get_offset_of_slice(foo), Some(0));
335    /// assert_eq!(string.get_offset_of_slice(bar), Some(4));
336    /// assert_eq!(string.get_offset_of_slice(baz), Some(8));
337    /// assert_eq!(string.get_offset_of_slice(&string[11..]), None);
338    ///
339    /// assert_eq!(string.get_offset_of_slice(&another), None);
340    ///
341    /// ```
342    fn get_offset_of_slice(&self, other: &Self) -> Option<usize>;
343
344    /// Returns the index of `other` if it's stored in the slice (if it points within the slice).
345    ///
346    /// If `other` is not inside `self`, this returns `self.len()`.
347    ///
348    /// # Example
349    ///
350    /// ### Called on slices
351    ///
352    /// ```
353    /// use core_extensions::SliceExt;
354    ///
355    /// let list = vec![0, 1, 2, 3, 4, 5];
356    ///
357    /// let other = [0, 1, 2, 3];
358    ///
359    /// assert_eq!(list.index_of(&list[0]), 0);
360    /// assert_eq!(list.index_of(&list[3]), 3);
361    /// assert_eq!(list.index_of(&list[5]), 5);
362    /// assert_eq!(list.index_of(list.as_ptr().wrapping_offset(6)), 6);
363    /// assert_eq!(list.index_of(list.as_ptr().wrapping_offset(7)), 6);
364    /// assert_eq!(list.index_of(&0), list.len());
365    ///
366    /// assert_eq!(list.index_of(&other[0]), list.len());
367    /// assert_eq!(list.index_of(&other[1]), list.len());
368    ///
369    /// ```
370    ///
371    /// ### Called on `str`s
372    ///
373    /// ```
374    /// use core_extensions::SliceExt;
375    ///
376    /// let string = String::from("abcdefgh");
377    /// let bytes = string.as_bytes();
378    ///
379    /// let other = b"abcdefgh";
380    ///
381    /// assert_eq!(string.index_of(&bytes[0]), 0);
382    /// assert_eq!(string.index_of(&bytes[3]), 3);
383    /// assert_eq!(string.index_of(&bytes[5]), 5);
384    /// assert_eq!(string.index_of(bytes.as_ptr().wrapping_offset(6)), 6);
385    /// assert_eq!(string.index_of(bytes.as_ptr().wrapping_offset(7)), 7);
386    /// assert_eq!(string.index_of(&0), string.len());
387    ///
388    /// assert_eq!(string.index_of(&other[0]), string.len());
389    /// assert_eq!(string.index_of(&other[1]), string.len());
390    /// ```
391    fn index_of(&self, other: *const Self::Elem) -> usize;
392
393    /// Returns the index of `other` if it's stored in the slice (if it points within the slice).
394    ///
395    /// If `other` is not inside `self`, this returns `None`.
396    ///
397    /// # Example
398    ///
399    /// ### Called on slices
400    ///
401    /// ```
402    /// use core_extensions::SliceExt;
403    ///
404    /// let list = vec![0, 1, 2, 3, 4, 5];
405    ///
406    /// let other = [0, 1, 2, 3];
407    ///
408    /// assert_eq!(list.get_index_of(&list[0]), Some(0));
409    /// assert_eq!(list.get_index_of(&list[3]), Some(3));
410    /// assert_eq!(list.get_index_of(&list[5]), Some(5));
411    /// assert_eq!(list.get_index_of(list.as_ptr().wrapping_offset(6)), None);
412    /// assert_eq!(list.get_index_of(list.as_ptr().wrapping_offset(7)), None);
413    /// assert_eq!(list.get_index_of(&0), None);
414    ///
415    /// assert_eq!(list.get_index_of(&other[0]), None);
416    /// assert_eq!(list.get_index_of(&other[1]), None);
417    ///
418    /// ```
419    ///
420    /// ### Called on `str`s
421    ///
422    /// ```
423    /// use core_extensions::SliceExt;
424    ///
425    /// let string = String::from("abcdefgh");
426    /// let bytes = string.as_bytes();
427    ///
428    /// let other = b"abcdefgh";
429    ///
430    /// assert_eq!(string.get_index_of(&bytes[0]), Some(0));
431    /// assert_eq!(string.get_index_of(&bytes[3]), Some(3));
432    /// assert_eq!(string.get_index_of(&bytes[5]), Some(5));
433    /// assert_eq!(string.get_index_of(bytes.as_ptr().wrapping_offset(6)), Some(6));
434    /// assert_eq!(string.get_index_of(bytes.as_ptr().wrapping_offset(7)), Some(7));
435    /// assert_eq!(string.get_index_of(&0), None);
436    ///
437    /// assert_eq!(string.get_index_of(&other[0]), None);
438    /// assert_eq!(string.get_index_of(&other[1]), None);
439    /// ```
440    fn get_index_of(&self, other: *const Self::Elem) -> Option<usize>;
441
442    /// Used for non-panicking slicing.
443    ///
444    /// If `range.end` is less than `range.start`, this returns an empty slice.
445    ///
446    /// # `bias` parameter
447    /// 
448    /// The `bias` parameter, by being converted into a [`SliceBias`], 
449    /// determines how this method handles invalid ranges.
450    ///
451    /// The impl for `[T]` ignores this parameter, saturating ranges at `self.len()`.
452    ///
453    /// For `str`, it grows the range in the directions determined by `bias` parameter.
454    ///
455    /// # Examples
456    ///
457    /// ### `[T]` slice
458    ///
459    /// ```
460    /// use core_extensions::SliceExt;
461    ///
462    /// let arr = [1, 2, 3, 4, 5, 6];
463    /// assert_eq!(arr.slice_lossy(0..3, ()), &arr[..3]);
464    /// assert_eq!(arr.slice_lossy(3..1000, ()), &arr[3..]);
465    /// assert_eq!(arr.slice_lossy(1000..1000, ()), &[]);
466    /// assert_eq!(arr.slice_lossy(1000..0, ()), &[]);
467    /// ```
468    ///
469    /// ### `str` slice
470    ///
471    /// ```
472    /// use core_extensions::SliceExt;
473    /// use core_extensions::slices::SliceBias;
474    ///
475    /// let word = "niño"; // 'ñ' is 2 bytes long , spanning the range 2..4
476    ///
477    /// assert_eq!(word.slice_lossy(0..3, SliceBias::LEFT ), "ni");
478    /// assert_eq!(word.slice_lossy(0..3, SliceBias::RIGHT), "niñ");
479    /// assert_eq!(word.slice_lossy(0..3, SliceBias::IN ), "ni");
480    /// assert_eq!(word.slice_lossy(0..3, SliceBias::OUT), "niñ");
481    ///
482    /// assert_eq!(word.slice_lossy(3..10000, ()), "ño");
483    /// assert_eq!(word.slice_lossy(3..10000, SliceBias::OUT), "ño");
484    ///
485    /// assert_eq!(word.slice_lossy(1000..1000, ()), "");
486    /// assert_eq!(word.slice_lossy(1000..1000, SliceBias::OUT), "");
487    /// assert_eq!(word.slice_lossy(1000..0, SliceBias::OUT), "");
488    /// ```
489    ///
490    /// [`SliceBias`]: struct.SliceBias.html
491    ///
492    fn slice_lossy<SB>(&self, range: Range<usize>, bias: SB) -> &Self
493    where
494        SB: Into<SliceBias>;
495
496    /// Used for non-panicking mutable slicing.
497    ///
498    /// Identical behavior to [`slice_lossy`](#tymethod.slice_lossy) with respect to ranges.
499    fn slice_lossy_mut<SB>(&mut self, range: Range<usize>, bias: SB) -> &mut Self
500    where
501        SB: Into<SliceBias>;
502}
503
504macro_rules! impl_common_slice_extensions {($T:ident) => {
505    type Elem = $T;
506
507    fn contains_slice(&self,other:&Self)->bool{
508        if other.is_empty() {
509            return false;
510        } else if mem::size_of::<$T>() == 0 {
511            return self.as_ptr() == other.as_ptr() && self.len() >= other.len(); 
512        }
513
514        let start_self  = self.as_ptr() as usize;
515        let end_self    = start_self + self.len() * mem::size_of::<$T>();
516        let start_other = other.as_ptr() as usize;
517        let end_other   = start_other + other.len() * mem::size_of::<$T>();
518        start_self <= start_other && end_other <= end_self
519    }
520
521    fn is_slice(&self,other:&Self)->bool{
522        self.as_ptr() as usize == other.as_ptr() as usize &&
523        self.len() == other.len()
524    }
525
526    fn offset_of_slice(&self,other:&Self)->usize{
527        if mem::size_of::<$T>() == 0 {
528            return if self.as_ptr() == other.as_ptr() {
529                0
530            } else {
531                self.len()
532            }
533        }
534        let offset = (other.as_ptr() as usize).wrapping_sub(self.as_ptr() as usize);
535        cmp::min(self.len(),offset / mem::size_of::<$T>())
536    }
537
538    fn get_offset_of_slice(&self,other:&Self)->Option<usize>{
539        if mem::size_of::<$T>() == 0 {
540            if self.as_ptr() == other.as_ptr() {
541                Some(0)
542            } else {
543                None
544            }
545        } else if self.contains_slice(other) {
546            Some((other.as_ptr() as usize - self.as_ptr() as usize)/mem::size_of::<$T>())
547        }else{
548            None
549        }
550    }
551
552    fn index_of(&self,other:*const $T)->usize{
553        if mem::size_of::<$T>() == 0 {
554            return if self.as_ptr() == other {
555                0
556            } else {
557                self.len()
558            };
559        }
560        let offset = (other as *const $T as usize).wrapping_sub(self.as_ptr() as usize);
561        cmp::min(self.len(), offset / mem::size_of::<$T>())
562    }
563
564    fn get_index_of(&self,other:*const $T)->Option<usize>{
565        if mem::size_of::<$T>() == 0 {
566            return if self.as_ptr() == other {
567                Some(0)
568            } else {
569                None
570            };
571        }
572
573        let sub = (other as *const $T as usize)
574            .wrapping_sub(self.as_ptr() as usize)
575            /mem::size_of::<$T>();
576
577        if sub >= self.len() {
578            None
579        } else {
580            Some(sub)
581        }
582    }
583
584}}
585
586mod str_impls {
587    use super::*;
588
589    fn lossy_str_range(this: &str, mut range: Range<usize>, bias: SliceBias) -> Range<usize> {
590        #[inline]
591        fn bias_bound(this: &str, mut index: usize, bias: BiasDirection) -> usize {
592            if index > this.len() {
593                return this.len();
594            }
595            
596            match bias {
597                BiasDirection::Left => {
598                    while !this.is_char_boundary(index) {
599                        index -= 1;
600                    }
601                },
602                BiasDirection::Right => {
603                    while !this.is_char_boundary(index) {
604                        index += 1;
605                    }
606                },
607            };
608
609            index
610        }
611        range.start = bias_bound(this, range.start, bias.start);
612        range.end = bias_bound(this, range.end, bias.end);
613        range.end = cmp::max(range.start, range.end);
614        range
615    }
616    impl SliceExt for str {
617        impl_common_slice_extensions! {u8}
618
619        fn slice_lossy<SB>(&self, range: Range<usize>, bias: SB) -> &Self
620        where
621            SB: Into<SliceBias>,
622        {
623            &self[lossy_str_range(self, range, bias.into())]
624        }
625
626        fn slice_lossy_mut<SB>(&mut self, range: Range<usize>, bias: SB) -> &mut Self
627        where
628            SB: Into<SliceBias>,
629        {
630            let r = lossy_str_range(self, range, bias.into());
631            &mut self[r]
632        }
633    }
634}
635
636mod slice_impls {
637    use super::*;
638
639    fn lossy_range<T>(this: &[T], mut range: Range<usize>) -> Range<usize> {
640        let len = this.len();
641        range.end = cmp::min(range.end, len);
642        range.start = cmp::min(range.start, range.end);
643        range
644    }
645
646    impl<T> SliceExt for [T] {
647        impl_common_slice_extensions! {T}
648
649        fn slice_lossy<SB>(&self, range: Range<usize>, _bias: SB) -> &Self {
650            &self[lossy_range(self, range)]
651        }
652
653        fn slice_lossy_mut<SB>(&mut self, range: Range<usize>, _bias: SB) -> &mut Self {
654            let r = lossy_range(self, range);
655            &mut self[r]
656        }
657    }
658}
659
660#[cfg(test)]
661mod tests {
662    #![allow(clippy::bool_assert_comparison)]
663
664    use super::*;
665
666    #[cfg(feature = "alloc")]
667    use alloc::{
668        vec::Vec,
669        string::String,
670    };
671
672    struct Unpromoted<T> {
673        inner: T,
674        _dummy:  std_::cell::Cell<u32>,
675    }
676    #[allow(non_snake_case)]
677    fn Unpromoted<T>(inner: T) -> Unpromoted<T> {
678        Unpromoted {
679            inner,
680            _dummy: std_::cell::Cell::new(10),
681        }
682    }
683    impl<T> std_::ops::Deref for Unpromoted<T> {
684        type Target = T;
685        fn deref(&self) -> &T {
686            &self.inner
687        }
688    }
689
690    #[test]
691    fn contains_slice() {
692        fn inner<T>(list: &[T; 12]){
693            let slice_a = &list[0..4];
694            let slice_b = &list[4..8];
695            let slice_c = &list[8..12];
696
697            assert_eq!(slice_b.contains_slice(&slice_a[3..]), false);
698            assert_eq!(slice_b.contains_slice(&slice_a[4..]), false);
699
700            assert_eq!(slice_b.contains_slice(&slice_b[0..]), true);
701            assert_eq!(slice_b.contains_slice(&slice_b[1..]), true);
702            assert_eq!(slice_b.contains_slice(&slice_b[2..]), true);
703            assert_eq!(slice_b.contains_slice(&slice_b[3..]), true);
704            
705            assert_eq!(slice_b.contains_slice(&slice_c[0..0]), false);
706            assert_eq!(slice_b.contains_slice(&slice_c[0..]), false);
707            assert_eq!(slice_b.contains_slice(&slice_c[1..]), false);
708        }
709
710        inner(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
711        inner(&[0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
712        inner(&[""; 12]);
713
714        {
715            let list = [(); 12];
716            let slice_a = &list[0..4];
717            let slice_b = &list[4..8];
718            let slice_c = &list[8..12];
719            
720            let other = Unpromoted([(); 12]);
721
722            assert_eq!(slice_b.contains_slice(&slice_a[3..]), true);
723            assert_eq!(slice_b.contains_slice(&slice_a[4..]), false);
724
725            assert_eq!(slice_b.contains_slice(&slice_b[0..]), true);
726            assert_eq!(slice_b.contains_slice(&slice_b[1..]), true);
727            assert_eq!(slice_b.contains_slice(&slice_b[2..]), true);
728            assert_eq!(slice_b.contains_slice(&slice_b[3..]), true);
729            
730            assert_eq!(slice_b.contains_slice(&slice_c[0..]), true);
731            assert_eq!(slice_b.contains_slice(&slice_c[1..]), true);
732            
733            assert_eq!(list.contains_slice(&*other), false);
734            assert_eq!(slice_a.contains_slice(&*other), false);
735            assert_eq!(slice_b.contains_slice(&*other), false);
736            assert_eq!(slice_c.contains_slice(&*other), false);
737
738            assert_eq!(other.contains_slice(&list), false);
739            assert_eq!(other.contains_slice(slice_a), false);
740            assert_eq!(other.contains_slice(slice_b), false);
741            assert_eq!(other.contains_slice(slice_c), false);
742        }
743    }
744    #[test]
745    fn offset_of_slice() {
746        fn inner<T>(list: &[T; 12]){
747            let slice_a = &list[0..4];
748            let slice_b = &list[4..8];
749            let slice_c = &list[8..12];
750
751            assert_eq!(slice_b.offset_of_slice(&slice_a[3..]), slice_b.len());
752
753            assert_eq!(slice_b.offset_of_slice(&slice_b[0..]), 0);
754            assert_eq!(slice_b.offset_of_slice(&slice_b[1..]), 1);
755            assert_eq!(slice_b.offset_of_slice(&slice_b[2..]), 2);
756            assert_eq!(slice_b.offset_of_slice(&slice_b[3..]), 3);
757            
758            assert_eq!(slice_b.offset_of_slice(&slice_c[0..]), slice_b.len());
759            assert_eq!(slice_b.offset_of_slice(&slice_c[1..]), slice_b.len());
760        }
761
762        inner(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
763        inner(&[0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
764        inner(&[""; 12]);
765
766        {
767            let list = [(); 12];
768            let slice_a = &list[0..4];
769            let slice_b = &list[4..8];
770            let slice_c = &list[8..12];
771            
772            let other = Unpromoted([(); 12]);
773
774            assert_eq!(slice_b.offset_of_slice(&slice_a[3..]), 0);
775
776            assert_eq!(slice_b.offset_of_slice(&slice_b[0..]), 0);
777            assert_eq!(slice_b.offset_of_slice(&slice_b[1..]), 0);
778            assert_eq!(slice_b.offset_of_slice(&slice_b[2..]), 0);
779            assert_eq!(slice_b.offset_of_slice(&slice_b[3..]), 0);
780            
781            assert_eq!(slice_b.offset_of_slice(&slice_c[0..]), 0);
782            assert_eq!(slice_b.offset_of_slice(&slice_c[1..]), 0);
783
784            assert_eq!(list.offset_of_slice(&*other), 12);
785            assert_eq!(slice_a.offset_of_slice(&*other), 4);
786            assert_eq!(slice_b.offset_of_slice(&*other), 4);
787            assert_eq!(slice_c.offset_of_slice(&*other), 4);
788
789            assert_eq!(other.offset_of_slice(&list), 12);
790            assert_eq!(other.offset_of_slice(slice_a), 12);
791            assert_eq!(other.offset_of_slice(slice_b), 12);
792            assert_eq!(other.offset_of_slice(slice_c), 12);
793        }
794    }
795    #[test]
796    fn get_offset_of_slice() {
797        fn inner<T>(list: &[T; 12]){
798            let slice_a = &list[0..4];
799            let slice_b = &list[4..8];
800            let slice_c = &list[8..12];
801
802            assert_eq!(slice_b.get_offset_of_slice(&slice_a[3..]), None);
803
804            assert_eq!(slice_b.get_offset_of_slice(&slice_b[1..1]), None);
805            assert_eq!(slice_b.get_offset_of_slice(&slice_b[0..]), Some(0));
806            assert_eq!(slice_b.get_offset_of_slice(&slice_b[1..]), Some(1));
807            assert_eq!(slice_b.get_offset_of_slice(&slice_b[2..]), Some(2));
808            assert_eq!(slice_b.get_offset_of_slice(&slice_b[3..]), Some(3));
809            
810            assert_eq!(slice_b.get_offset_of_slice(&slice_c[0..]), None);
811            assert_eq!(slice_b.get_offset_of_slice(&slice_c[1..]), None);
812        }
813
814        inner(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
815        inner(&[0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
816        inner(&[""; 12]);
817
818        {
819            let list = [(); 12];
820            let slice_a = &list[0..4];
821            let slice_b = &list[4..8];
822            let slice_c = &list[8..12];
823
824            let other = Unpromoted([(); 12]);
825
826            assert_eq!(slice_b.get_offset_of_slice(&slice_a[3..]), Some(0));
827
828            assert_eq!(slice_b.get_offset_of_slice(&slice_b[0..]), Some(0));
829            assert_eq!(slice_b.get_offset_of_slice(&slice_b[1..]), Some(0));
830            assert_eq!(slice_b.get_offset_of_slice(&slice_b[2..]), Some(0));
831            assert_eq!(slice_b.get_offset_of_slice(&slice_b[3..]), Some(0));
832            
833            assert_eq!(slice_b.get_offset_of_slice(&slice_c[0..]), Some(0));
834            assert_eq!(slice_b.get_offset_of_slice(&slice_c[1..]), Some(0));
835            
836            assert_eq!(list.get_offset_of_slice(&*other), None);
837            assert_eq!(slice_a.get_offset_of_slice(&*other), None);
838            assert_eq!(slice_b.get_offset_of_slice(&*other), None);
839            assert_eq!(slice_c.get_offset_of_slice(&*other), None);
840
841            assert_eq!(other.get_offset_of_slice(&list), None);
842            assert_eq!(other.get_offset_of_slice(slice_a), None);
843            assert_eq!(other.get_offset_of_slice(slice_b), None);
844            assert_eq!(other.get_offset_of_slice(slice_c), None);
845        }
846    }
847    #[test]
848    fn index_of() {
849        fn inner<T>(list: &[T; 12]){
850            let slice_a = &list[0..4];
851            let slice_b = &list[4..8];
852            let slice_c = &list[8..12];
853
854            assert_eq!(slice_b.index_of(&slice_a[3]), slice_b.len());
855
856            assert_eq!(slice_b.index_of(&slice_b[0]), 0);
857            assert_eq!(slice_b.index_of(&slice_b[1]), 1);
858            assert_eq!(slice_b.index_of(&slice_b[2]), 2);
859            assert_eq!(slice_b.index_of(&slice_b[3]), 3);
860            
861            assert_eq!(slice_b.index_of(&slice_c[0]), slice_b.len());
862            assert_eq!(slice_b.index_of(&slice_c[1]), slice_b.len());
863        }
864
865        inner(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
866        inner(&[0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
867        inner(&[""; 12]);
868
869        {
870            let list = [(); 12];
871            let slice_a = &list[0..4];
872            let slice_b = &list[4..8];
873            let slice_c = &list[8..12];
874            
875            let other = Unpromoted([(); 12]);
876
877            assert_eq!(slice_b.index_of(&slice_a[3]), 0);
878
879            assert_eq!(slice_b.index_of(&slice_b[0]), 0);
880            assert_eq!(slice_b.index_of(&slice_b[1]), 0);
881            assert_eq!(slice_b.index_of(&slice_b[2]), 0);
882            assert_eq!(slice_b.index_of(&slice_b[3]), 0);
883            
884            assert_eq!(slice_b.index_of(&slice_c[0]), 0);
885            assert_eq!(slice_b.index_of(&slice_c[1]), 0);
886
887            assert_eq!(list.index_of(&other[0]), 12);
888            assert_eq!(slice_a.index_of(&other[0]), 4);
889            assert_eq!(slice_b.index_of(&other[0]), 4);
890            assert_eq!(slice_c.index_of(&other[0]), 4);
891
892            assert_eq!(other.index_of(&list[0]), 12);
893            assert_eq!(other.index_of(&slice_a[0]), 12);
894            assert_eq!(other.index_of(&slice_b[0]), 12);
895            assert_eq!(other.index_of(&slice_c[0]), 12);
896        }
897    }
898    #[test]
899    fn get_index_of() {
900        fn inner<T>(list: &[T; 12]){
901            let slice_a = &list[0..4];
902            let slice_b = &list[4..8];
903            let slice_c = &list[8..12];
904
905            assert_eq!(slice_b.get_index_of(&slice_a[3]), None);
906
907            assert_eq!(slice_b.get_index_of(&slice_b[0]), Some(0));
908            assert_eq!(slice_b.get_index_of(&slice_b[1]), Some(1));
909            assert_eq!(slice_b.get_index_of(&slice_b[2]), Some(2));
910            assert_eq!(slice_b.get_index_of(&slice_b[3]), Some(3));
911            
912            assert_eq!(slice_b.get_index_of(&slice_c[0]), None);
913            assert_eq!(slice_b.get_index_of(&slice_c[1]), None);
914        }
915
916        inner(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
917        inner(&[0u32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
918        inner(&[""; 12]);
919
920        {
921            let list = [(); 12];
922            let slice_a = &list[0..4];
923            let slice_b = &list[4..8];
924            let slice_c = &list[8..12];
925            
926            let other = Unpromoted([(); 12]);
927
928            assert_eq!(slice_b.get_index_of(&slice_a[3]), Some(0));
929
930            assert_eq!(slice_b.get_index_of(&slice_b[0]), Some(0));
931            assert_eq!(slice_b.get_index_of(&slice_b[1]), Some(0));
932            assert_eq!(slice_b.get_index_of(&slice_b[2]), Some(0));
933            assert_eq!(slice_b.get_index_of(&slice_b[3]), Some(0));
934            
935            assert_eq!(slice_b.get_index_of(&slice_c[0]), Some(0));
936            assert_eq!(slice_b.get_index_of(&slice_c[1]), Some(0));
937            
938            assert_eq!(list.get_index_of(&other[0]), None);
939            assert_eq!(slice_a.get_index_of(&other[0]), None);
940            assert_eq!(slice_b.get_index_of(&other[0]), None);
941            assert_eq!(slice_c.get_index_of(&other[0]), None);
942
943            assert_eq!(other.get_index_of(&list[0]), None);
944            assert_eq!(other.get_index_of(&slice_a[0]), None);
945            assert_eq!(other.get_index_of(&slice_b[0]), None);
946            assert_eq!(other.get_index_of(&slice_c[0]), None);
947        }
948    }
949    #[test]
950    #[cfg(feature = "alloc")]
951    fn slice_lossy_slice_examples() {
952        let list = [0, 1, 2, 3, 4, 5];
953        assert_eq!(list.slice_lossy(0..list.len(), ()), &list[..]);
954        assert_eq!(list.slice_lossy(0..1000, ()), &list[..]);
955        assert_eq!(list.slice_lossy(0..1000, ()), &list[..]);
956        assert_eq!(list.slice_lossy(10..10000, ()), &list[list.len()..]);
957        assert_eq!(list.slice_lossy(3..10000, ()), &list[3..]);
958        assert_eq!(list.slice_lossy(0..3, ()), &list[..3]);
959        assert_eq!(list.slice_lossy(0..2, ()), &list[..2]);
960        assert_eq!(list.slice_lossy(0..1, ()), &list[..1]);
961        assert_eq!(list.slice_lossy(0..0, ()), &list[..0]);
962    }
963    #[test]
964    fn slice_lossy_str_examples() {
965        let word = "niño";
966        assert_eq!(word.len(), 5);
967
968        assert!(word
969            .slice_lossy(0..word.len(), SliceBias::OUT)
970            .is_slice(word));
971        assert!(word
972            .slice_lossy(0..1000, SliceBias::OUT)
973            .is_slice(word));
974        assert!(word
975            .slice_lossy(0..1000, SliceBias::OUT)
976            .is_slice(word));
977        assert!(word
978            .slice_lossy(10..10000, SliceBias::OUT)
979            .is_slice(&word[word.len()..]));
980        assert!(word.slice_lossy(0..4, SliceBias::OUT).is_slice(&word[..4]));
981        assert!(word.slice_lossy(0..3, SliceBias::OUT).is_slice(&word[..4]));
982        assert!(word.slice_lossy(0..2, SliceBias::OUT).is_slice(&word[..2]));
983
984        assert!(word
985            .slice_lossy(10..10000, SliceBias::IN)
986            .is_slice(&word[word.len()..]));
987        assert!(word.slice_lossy(0..4, SliceBias::IN).is_slice(&word[0..4]));
988        assert!(word.slice_lossy(0..3, SliceBias::IN).is_slice(&word[0..2]));
989        assert!(word.slice_lossy(3..3, SliceBias::IN).is_slice(&word[4..4]));
990        assert!(word.slice_lossy(3..4, SliceBias::IN).is_slice(&word[4..4]));
991        assert!(word.slice_lossy(2..3, SliceBias::IN).is_slice(&word[2..2]));
992        assert!(word.slice_lossy(0..2, SliceBias::IN).is_slice(&word[0..2]));
993
994        assert!(word
995            .slice_lossy(10..10000, SliceBias::LEFT)
996            .is_slice(&word[word.len()..]));
997        assert!(word
998            .slice_lossy(0..4, SliceBias::LEFT)
999            .is_slice(&word[0..4]));
1000        assert!(word
1001            .slice_lossy(0..3, SliceBias::LEFT)
1002            .is_slice(&word[0..2]));
1003        assert!(word
1004            .slice_lossy(3..3, SliceBias::LEFT)
1005            .is_slice(&word[2..2]));
1006        assert!(word
1007            .slice_lossy(3..4, SliceBias::LEFT)
1008            .is_slice(&word[2..4]));
1009        assert!(word
1010            .slice_lossy(2..3, SliceBias::LEFT)
1011            .is_slice(&word[2..2]));
1012        assert!(word
1013            .slice_lossy(0..2, SliceBias::LEFT)
1014            .is_slice(&word[0..2]));
1015
1016        assert!(word
1017            .slice_lossy(10..10000, SliceBias::RIGHT)
1018            .is_slice(&word[word.len()..]));
1019        assert!(word
1020            .slice_lossy(0..4, SliceBias::RIGHT)
1021            .is_slice(&word[0..4]));
1022        assert!(word
1023            .slice_lossy(0..3, SliceBias::RIGHT)
1024            .is_slice(&word[0..4]));
1025        assert!(word
1026            .slice_lossy(3..3, SliceBias::RIGHT)
1027            .is_slice(&word[4..4]));
1028        assert!(word
1029            .slice_lossy(3..4, SliceBias::RIGHT)
1030            .is_slice(&word[4..4]));
1031        assert!(word
1032            .slice_lossy(2..3, SliceBias::RIGHT)
1033            .is_slice(&word[2..4]));
1034        assert!(word
1035            .slice_lossy(0..2, SliceBias::RIGHT)
1036            .is_slice(&word[0..2]));
1037
1038        let sub_word = word.slice_lossy(3..10000, SliceBias::OUT);
1039        assert_eq!(sub_word, &word[2..]);
1040        assert_eq!(sub_word, "ño");
1041    }
1042
1043    #[test]
1044    #[cfg(feature = "alloc")]
1045    // Too slow to run in miri, and there's no unsafe code here.
1046    #[cfg(not(miri))]
1047    #[cfg(feature = "rand")]
1048    fn slice_lossy_slice_no_panic() {
1049        use rand::Rng;
1050
1051        let mut rng = ::rand::thread_rng();
1052        for _ in 0..50 {
1053            let slice_len = rng.gen_range(0, 100);
1054            let slice_ = rng.gen_iter::<usize>().take(slice_len).collect::<Vec<_>>();
1055            for _ in 0..500 {
1056                let start = if slice_len == 0 {
1057                    0
1058                } else {
1059                    rng.gen_range(0, slice_len * 2)
1060                };
1061                let end = if slice_len == 0 {
1062                    0
1063                } else {
1064                    rng.gen_range(0, slice_len * 2)
1065                };
1066                slice_.slice_lossy(start..end, rng.gen::<SliceBias>());
1067            }
1068        }
1069    }
1070
1071    #[test]
1072    #[cfg(feature = "rand")]
1073    #[cfg(feature = "alloc")]
1074    // Too slow to run in miri, and there's no unsafe code here.
1075    #[cfg(not(miri))]
1076    fn slice_lossy_str_no_panic() {
1077        use rand::Rng;
1078
1079        let mut rng = ::rand::thread_rng();
1080        for _ in 0..50 {
1081            let char_len = rng.gen_range(0, 100);
1082            let string = rng.gen_iter::<char>().take(char_len).collect::<String>();
1083            let slice_len = string.len();
1084            for _ in 0..500 {
1085                let start = if slice_len == 0 {
1086                    0
1087                } else {
1088                    rng.gen_range(0, slice_len * 2)
1089                };
1090                let end = if slice_len == 0 {
1091                    0
1092                } else {
1093                    rng.gen_range(0, slice_len * 2)
1094                };
1095                string.slice_lossy(start..end, rng.gen::<SliceBias>());
1096            }
1097        }
1098    }
1099}