1use core::convert::TryInto;
3use core::hint::unreachable_unchecked;
4use core::num::TryFromIntError;
5use core::ops::{Range, RangeFrom, RangeTo};
20use core::slice::SliceIndex;
21
22use self::sealed::{IndexSealed, IntoIntIndex};
23
24pub trait SliceIntExt: sealed::SealedSliceIntExt {
26 fn get_int<T>(&self, idx: T) -> Option<&'_ <T as sealed::IntSliceIndex<Self>>::Output>
48 where
49 T: IntSliceIndex<Self>;
50
51 fn get_int_mut<T>(
70 &mut self,
71 idx: T,
72 ) -> Option<&'_ mut <T as sealed::IntSliceIndex<Self>>::Output>
73 where
74 T: IntSliceIndex<Self>;
75
76 unsafe fn get_int_unchecked<T>(&self, idx: T) -> &'_ <T as sealed::IntSliceIndex<Self>>::Output
95 where
96 T: IntSliceIndex<Self>;
97
98 unsafe fn get_int_unchecked_mut<T>(
121 &mut self,
122 idx: T,
123 ) -> &'_ mut <T as sealed::IntSliceIndex<Self>>::Output
124 where
125 T: IntSliceIndex<Self>;
126}
127
128pub trait IntSliceIndex<T: ?Sized>: sealed::SealedSliceIndex<T> {}
142
143pub(crate) mod sealed {
171 use core::num::TryFromIntError;
172
173 pub trait IndexSealed {
180 fn copy(&self) -> Self;
182 #[cold]
183 fn panic_msg(limit: usize, idx: Self) -> !;
184 }
185
186 pub trait IntoIntIndex {
191 type IntoIndex;
192 fn index(self) -> Result<Self::IntoIndex, TryFromIntError>;
193 }
194
195 pub trait IntSliceIndex<T: ?Sized>: Sized {
200 type Output: ?Sized;
201 fn get(self, slice: &T) -> Option<&Self::Output>;
202 fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
203 unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
204 unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
205 fn index(self, slice: &T) -> &Self::Output;
206 fn index_mut(self, slice: &mut T) -> &mut Self::Output;
207 }
208
209 pub trait SealedSliceIntExt {}
213
214 pub trait SealedSliceIndex<T: ?Sized>: IntSliceIndex<T> {
219 type Output: ?Sized;
220 fn get(self, _: &T) -> ! {
221 unreachable!()
222 }
223 fn get_mut(self, _: &mut T) -> ! {
224 unreachable!()
225 }
226 unsafe fn get_unchecked(self, _: &T) -> ! {
227 unreachable!()
228 }
229 unsafe fn get_unchecked_mut(self, _: &mut T) -> ! {
230 unreachable!()
231 }
232 fn index(self, _: &T) -> ! {
233 unreachable!()
234 }
235 fn index_mut(self, _: &mut T) -> ! {
236 unreachable!()
237 }
238 }
239
240 impl<U: ?Sized, T: IntSliceIndex<U>> SealedSliceIndex<U> for T {
241 type Output = <Self as IntSliceIndex<U>>::Output;
242 }
243}
244
245impl<U> sealed::SealedSliceIntExt for [U] {}
246
247impl<U> SliceIntExt for [U] {
248 fn get_int<T>(&self, idx: T) -> Option<&'_ <T as sealed::IntSliceIndex<Self>>::Output>
249 where
250 T: IntSliceIndex<Self>,
251 {
252 <T as sealed::IntSliceIndex<Self>>::get(idx, self)
253 }
254
255 fn get_int_mut<T>(
256 &mut self,
257 idx: T,
258 ) -> Option<&'_ mut <T as sealed::IntSliceIndex<Self>>::Output>
259 where
260 T: IntSliceIndex<Self>,
261 {
262 <T as sealed::IntSliceIndex<Self>>::get_mut(idx, self)
263 }
264
265 unsafe fn get_int_unchecked<T>(&self, idx: T) -> &'_ <T as sealed::IntSliceIndex<Self>>::Output
266 where
267 T: IntSliceIndex<Self>,
268 {
269 unsafe { <T as sealed::IntSliceIndex<Self>>::get_unchecked(idx, self) }
271 }
272
273 unsafe fn get_int_unchecked_mut<T>(
274 &mut self,
275 idx: T,
276 ) -> &'_ mut <T as sealed::IntSliceIndex<Self>>::Output
277 where
278 T: IntSliceIndex<Self>,
279 {
280 unsafe { <T as sealed::IntSliceIndex<Self>>::get_unchecked_mut(idx, self) }
282 }
283}
284
285impl sealed::SealedSliceIntExt for str {}
286
287impl SliceIntExt for str {
288 fn get_int<T>(&self, idx: T) -> Option<&'_ <T as sealed::IntSliceIndex<Self>>::Output>
289 where
290 T: IntSliceIndex<Self>,
291 {
292 <T as sealed::IntSliceIndex<Self>>::get(idx, self)
293 }
294
295 fn get_int_mut<T>(
296 &mut self,
297 idx: T,
298 ) -> Option<&'_ mut <T as sealed::IntSliceIndex<Self>>::Output>
299 where
300 T: IntSliceIndex<Self>,
301 {
302 <T as sealed::IntSliceIndex<Self>>::get_mut(idx, self)
303 }
304
305 unsafe fn get_int_unchecked<T>(&self, idx: T) -> &'_ <T as sealed::IntSliceIndex<Self>>::Output
306 where
307 T: IntSliceIndex<Self>,
308 {
309 unsafe { <T as sealed::IntSliceIndex<Self>>::get_unchecked(idx, self) }
311 }
312
313 unsafe fn get_int_unchecked_mut<T>(
314 &mut self,
315 idx: T,
316 ) -> &'_ mut <T as sealed::IntSliceIndex<Self>>::Output
317 where
318 T: IntSliceIndex<Self>,
319 {
320 unsafe { <T as sealed::IntSliceIndex<Self>>::get_unchecked_mut(idx, self) }
322 }
323}
324
325#[repr(transparent)]
340#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
341pub struct TryIndex<T>(pub T);
342
343impl<T> TryIndex<T>
344where
345 T: TryInto<usize>,
346 T::Error: Into<TryFromIntError>,
347{
348 fn into_int_index(self) -> usize {
349 match self.0.try_into() {
350 Ok(idx) => idx,
351 Err(error) => panic!("Invalid index, {}", error.into()),
352 }
353 }
354}
355
356impl<T> IntoIntIndex for TryIndex<T>
357where
358 T: TryInto<usize>,
359 T::Error: Into<TryFromIntError>,
360{
361 type IntoIndex = usize;
362 fn index(self) -> Result<usize, TryFromIntError> {
363 self.0.try_into().map_err(Into::into)
364 }
365}
366
367impl<T, U> sealed::IntSliceIndex<[U]> for TryIndex<T>
368where
369 T: TryInto<usize>,
370 T::Error: Into<TryFromIntError>,
371{
372 type Output = U;
373 fn get(self, slice: &[U]) -> Option<&Self::Output> {
374 match IntoIntIndex::index(self) {
375 Ok(idx) => slice.get(idx),
376 Err(_) => None,
377 }
378 }
379 fn get_mut(self, slice: &mut [U]) -> Option<&mut Self::Output> {
380 match IntoIntIndex::index(self) {
381 Ok(idx) => slice.get_mut(idx),
382 Err(_) => None,
383 }
384 }
385 unsafe fn get_unchecked(self, slice: &[U]) -> &Self::Output {
386 let idx = self.into_int_index();
388 unsafe { slice.get_unchecked(idx) }
389 }
390 unsafe fn get_unchecked_mut(self, slice: &mut [U]) -> &mut Self::Output {
391 let idx = self.into_int_index();
393 unsafe { slice.get_unchecked_mut(idx) }
394 }
395 fn index(self, slice: &[U]) -> &Self::Output {
396 &slice[self.into_int_index()]
397 }
398 fn index_mut(self, slice: &mut [U]) -> &mut Self::Output {
399 &mut slice[self.into_int_index()]
400 }
401}
402
403impl<T, U> IntSliceIndex<[U]> for TryIndex<T>
404where
405 T: TryInto<usize>,
406 T::Error: Into<TryFromIntError>,
407{
408}
409
410impl<T, U> core::ops::Index<TryIndex<T>> for [U]
411where
412 T: TryInto<usize> + IndexSealed,
413 T::Error: Into<TryFromIntError>,
414{
415 type Output = U;
416 fn index(&self, idx: TryIndex<T>) -> &U {
417 sealed::IntSliceIndex::index(idx, self)
418 }
419}
420
421impl<T, U> core::ops::IndexMut<TryIndex<T>> for [U]
422where
423 T: TryInto<usize> + IndexSealed,
424 T::Error: Into<TryFromIntError>,
425{
426 fn index_mut(&mut self, idx: TryIndex<T>) -> &mut Self::Output {
427 sealed::IntSliceIndex::index_mut(idx, self)
428 }
429}
430
431#[repr(transparent)]
447#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
448pub struct Intex<T>(pub T);
449
450impl<T, U> core::ops::Index<Intex<T>> for [U]
451where
452 T: IntSliceIndex<[U]> + IndexSealed,
453{
454 type Output = <T as sealed::IntSliceIndex<[U]>>::Output;
455
456 fn index(&self, idx: Intex<T>) -> &Self::Output {
457 <T as sealed::IntSliceIndex<[U]>>::index(idx.0, self)
458 }
459}
460
461impl<T, U> core::ops::IndexMut<Intex<T>> for [U]
462where
463 T: IntSliceIndex<[U]> + IndexSealed,
464{
465 fn index_mut(&mut self, idx: Intex<T>) -> &mut Self::Output {
466 <T as sealed::IntSliceIndex<[U]>>::index_mut(idx.0, self)
467 }
468}
469
470impl<T: TryInto<usize>> sealed::IntoIntIndex for Range<T>
475where
476 TryFromIntError: From<T::Error>,
477{
478 type IntoIndex = Range<usize>;
479 fn index(self) -> Result<Range<usize>, TryFromIntError> {
480 let Range { start, end } = self;
481 let start: usize = start.try_into()?;
482 let end: usize = end.try_into()?;
483 Ok(start..end)
484 }
485}
486
487impl<T: TryInto<usize>> sealed::IntoIntIndex for RangeTo<T>
488where
489 TryFromIntError: From<T::Error>,
490{
491 type IntoIndex = RangeTo<usize>;
492 fn index(self) -> Result<RangeTo<usize>, TryFromIntError> {
493 let end: usize = self.end.try_into()?;
494 Ok(..end)
495 }
496}
497
498impl<T: TryInto<usize>> sealed::IntoIntIndex for RangeFrom<T>
499where
500 TryFromIntError: From<T::Error>,
501{
502 type IntoIndex = RangeFrom<usize>;
503 fn index(self) -> Result<RangeFrom<usize>, TryFromIntError> {
504 let start: usize = self.start.try_into()?;
505 Ok(start..)
506 }
507}
508
509macro_rules! slice_index {
510($($t:ty),*) => {
511 $(slice_index!(@$t);)*
512};
513(@IntSliceIndex<[U]> for $t:ty: with IntoIntIndex) => {
514 impl<U> sealed::IntSliceIndex<[U]> for $t {
515 type Output = <<Self as sealed::IntoIntIndex>::IntoIndex as SliceIndex<[U]>>::Output;
516 fn get(self, slice: &[U]) -> Option<&Self::Output> {
517 match IntoIntIndex::index(self) {
518 Ok(idx) => slice.get(idx),
519 Err(_) => None,
520 }
521 }
522 fn get_mut(self, slice: &mut [U]) -> Option<&mut Self::Output> {
523 match IntoIntIndex::index(self) {
524 Ok(idx) => slice.get_mut(idx),
525 Err(_) => None,
526 }
527 }
528 unsafe fn get_unchecked(self, slice: &[U]) -> &Self::Output {
529 match IntoIntIndex::index(self) {
530 Ok(idx) => unsafe { slice.get_unchecked(idx) },
532 Err(_) => unsafe { unreachable_unchecked() },
535 }
536 }
537 unsafe fn get_unchecked_mut(self, slice: &mut [U]) -> &mut Self::Output {
538 match IntoIntIndex::index(self) {
539 Ok(idx) => unsafe { slice.get_unchecked_mut(idx) },
541 Err(_) => unsafe { unreachable_unchecked() },
544 }
545 }
546 fn index(self, slice: &[U]) -> &Self::Output {
547 match sealed::IntSliceIndex::get(IndexSealed::copy(&self), slice) {
548 Some(output) => output,
549 None => IndexSealed::panic_msg(slice.len(), self),
550 }
551 }
552 fn index_mut(self, slice: &mut [U]) -> &mut Self::Output {
553 let len = slice.len();
554 match sealed::IntSliceIndex::get_mut(IndexSealed::copy(&self), slice) {
555 Some(output) => output,
556 None => IndexSealed::panic_msg(len, self),
557 }
558 }
559 }
560};
561(@IntSliceIndex<str> for $t:ty: with IntoIntIndex) => {
562 impl sealed::IntSliceIndex<str> for $t {
563 type Output = <<Self as sealed::IntoIntIndex>::IntoIndex as SliceIndex<str>>::Output;
564 fn get(self, slice: &str) -> Option<&Self::Output> {
565 match IntoIntIndex::index(self) {
566 Ok(idx) => slice.get(idx),
567 Err(_) => None,
568 }
569 }
570 fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
571 match IntoIntIndex::index(self) {
572 Ok(idx) => slice.get_mut(idx),
573 Err(_) => None,
574 }
575 }
576 unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
577 match IntoIntIndex::index(self) {
578 Ok(idx) => unsafe { slice.get_unchecked(idx) },
580 Err(_) => unsafe { unreachable_unchecked() },
583 }
584 }
585 unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
586 match IntoIntIndex::index(self) {
587 Ok(idx) => unsafe { slice.get_unchecked_mut(idx) },
589 Err(_) => unsafe { unreachable_unchecked() },
592 }
593 }
594 fn index(self, slice: &str) -> &Self::Output {
595 match sealed::IntSliceIndex::get(IndexSealed::copy(&self), slice) {
596 Some(output) => output,
597 None => IndexSealed::panic_msg(slice.len(), self),
598 }
599 }
600 fn index_mut(self, slice: &mut str) -> &mut Self::Output {
601 let len = slice.len();
602 match sealed::IntSliceIndex::get_mut(IndexSealed::copy(&self), slice) {
603 Some(output) => output,
604 None => IndexSealed::panic_msg(len, self),
605 }
606 }
607 }
608};
609(@$t:ty) => {
610 impl sealed::IntoIntIndex for $t {
611 type IntoIndex = usize;
612 #[allow(clippy::needless_question_mark)]
618 fn index(self) -> Result<usize, TryFromIntError> {
619 Ok(self.try_into()?)
620 }
621 }
622
623 impl sealed::IndexSealed for $t {
624 #[inline(always)]
625 fn copy(&self) -> Self { *self }
626 #[cold]
627 fn panic_msg(len: usize, index: Self) -> ! {
628 panic!("index {} out of range for slice of length {}", index, len)
629 }
630 }
631
632 impl sealed::IndexSealed for Range<$t> {
633 #[inline(always)]
634 fn copy(&self) -> Self { Range { .. *self } }
635 #[cold]
636 fn panic_msg(len: usize, index: Self) -> ! {
637 panic!("index {} out of range for slice of length {}", index.end, len)
638 }
639 }
640
641 impl sealed::IndexSealed for RangeFrom<$t> {
642 #[inline(always)]
643 fn copy(&self) -> Self { RangeFrom { .. *self } }
644 #[cold]
645 fn panic_msg(len: usize, index: Self) -> ! {
646 panic!("index {} out of range for slice of length {}", index.start, len)
647 }
648 }
649
650 impl sealed::IndexSealed for RangeTo<$t> {
651 #[inline(always)]
652 fn copy(&self) -> Self { RangeTo { .. *self } }
653 #[cold]
654 fn panic_msg(len: usize, index: Self) -> ! {
655 panic!("index {} out of range for slice of length {}", index.end, len)
656 }
657 }
658
659 slice_index!(@IntSliceIndex<[U]> for $t: with IntoIntIndex);
660 slice_index!(@IntSliceIndex<[U]> for Range<$t>: with IntoIntIndex);
661 slice_index!(@IntSliceIndex<[U]> for RangeTo<$t>: with IntoIntIndex);
662 slice_index!(@IntSliceIndex<[U]> for RangeFrom<$t>: with IntoIntIndex);
663 slice_index!(@IntSliceIndex<str> for Range<$t>: with IntoIntIndex);
664 slice_index!(@IntSliceIndex<str> for RangeTo<$t>: with IntoIntIndex);
665 slice_index!(@IntSliceIndex<str> for RangeFrom<$t>: with IntoIntIndex);
666
667 impl<U> IntSliceIndex<[U]> for $t {}
668 impl<U> IntSliceIndex<[U]> for Range<$t> {}
669 impl<U> IntSliceIndex<[U]> for RangeTo<$t> {}
670 impl<U> IntSliceIndex<[U]> for RangeFrom<$t> {}
671
672 impl IntSliceIndex<str> for Range<$t> {}
673 impl IntSliceIndex<str> for RangeTo<$t> {}
674 impl IntSliceIndex<str> for RangeFrom<$t> {}
675} }
676
677slice_index!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);