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}