index_ext/
int.rs

1//! Defines wrappers around standard integers to use the as indices.
2use core::convert::TryInto;
3use core::hint::unreachable_unchecked;
4use core::num::TryFromIntError;
5/// Defines helper types for more integer indices.
6///
7/// There are helpers for adapting indices to implement the standard `ops::Index`/`ops::IndexMut`
8/// or the crate-wide [`IntSliceIndex`] respectively.
9///
10/// * [`TryIndex`] uses `TryInto<usize>` to convert an type into an index, slightly making them
11///   more convenient to use where the error conditions have been checked through external means or
12///   where such panicking is permissible.
13/// * [`Intex`] wraps an implementor of [`IntSliceIndex`] to turn it into an implementor of
14///   `ops::Index` and `ops::IndexMut` as well.
15///
16/// [`Intex`]: struct.Intex.html
17/// [`IntSliceIndex`]: ../trait.IntSliceIndex.html
18/// [`TryIndex`]: struct.TryIndex.html
19use core::ops::{Range, RangeFrom, RangeTo};
20use core::slice::SliceIndex;
21
22use self::sealed::{IndexSealed, IntoIntIndex};
23
24/// An extension trait allowing slices to be indexed by everything convertible to `usize`.
25pub trait SliceIntExt: sealed::SealedSliceIntExt {
26    /// Return a reference to an element or subslice with an integer index, or `None` if out of
27    /// bounds.
28    ///
29    /// This works like [`slice::get`] but allows arbitrary integers to be used as indices. It will
30    /// first try to convert them to an `usize`. For some types (`u8` and `u16`) this can never
31    /// fail while other types may refer to negative indices or are out-of-range. These cases are
32    /// treated as if the index was out-of-bounds due to the slice being too short.
33    ///
34    /// ## Examples
35    ///
36    /// ```
37    /// # use index_ext::SliceIntExt;
38    /// let v = [10, 40, 30];
39    /// assert_eq!(Some(&40), v.get_int(1u64));
40    /// assert_eq!(Some(&[10, 40][..]), v.get_int(0u8..2));
41    /// assert_eq!(None, v.get_int(3u8));
42    /// assert_eq!(None, v.get_int(0u8..4));
43    /// assert_eq!(None, v.get_int(-1i8));
44    /// ```
45    ///
46    /// [`slice::get`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get
47    fn get_int<T>(&self, idx: T) -> Option<&'_ <T as sealed::IntSliceIndex<Self>>::Output>
48    where
49        T: IntSliceIndex<Self>;
50
51    /// Return a mutable reference to an element or subslice with an integer index, or `None` if
52    /// out of bounds.
53    ///
54    /// This works like [`slice::get_mut`].
55    ///
56    /// ## Examples
57    ///
58    /// ```
59    /// # use index_ext::SliceIntExt;
60    /// let x = &mut [0, 1, 2];
61    ///
62    /// if let Some(elem) = x.get_int_mut(1u8) {
63    ///     *elem = 42;
64    /// }
65    /// assert_eq!(x, &[0, 42, 2]);
66    /// ```
67    ///
68    /// [`slice::get_mut`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_mut
69    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    /// Returns a reference to an element or subslice without doing bounds checking.
77    ///
78    /// ## Safety
79    ///
80    /// Like [`slice::get_unchecked`], calling this method with an out of bounds index is undefined
81    /// behaviour. _This includes indices for which conversion to a `usize` fails._
82    ///
83    /// [`slice::get_unchecked`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_unchecked
84    ///
85    /// ## Examples
86    /// ```
87    /// # use index_ext::SliceIntExt;
88    /// let x = &[1, 2, 4];
89    ///
90    /// unsafe {
91    ///     assert_eq!(x.get_int_unchecked(1i8), &2);
92    /// }
93    /// ```
94    unsafe fn get_int_unchecked<T>(&self, idx: T) -> &'_ <T as sealed::IntSliceIndex<Self>>::Output
95    where
96        T: IntSliceIndex<Self>;
97
98    /// Returns a mutable reference to an element or subslice without doing bounds checking.
99    ///
100    /// ## Safety
101    ///
102    /// Like [`slice::get_unchecked_mut`], calling this method with an out of bounds index is undefined
103    /// behaviour. _This includes indices for which conversion to a `usize` fails._
104    ///
105    /// ## Examples
106    ///
107    /// ```
108    /// # use index_ext::SliceIntExt;
109    /// let x = &mut [1, 2, 4];
110    ///
111    /// unsafe {
112    ///     let elem = x.get_int_unchecked_mut(1u64);
113    ///     *elem = 13;
114    /// }
115    ///
116    /// assert_eq!(x, &[1, 13, 4]);
117    /// ```
118    ///
119    /// [`slice::get_unchecked_mut`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_unchecked_mut
120    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
128/// A trait for mathematical integer based indices.
129///
130/// Any integer can be used as a fallible index where a machine word can be used by first trying to
131/// convert it into a `usize` and then indexing with the original method. From the point of the
132/// user, the effect is not much different. If `10usize` is out-of-bounds then so is any other
133/// integer representing the number `10`, no matter the allowed magnitude of its type. The same
134/// holds for integers that permit negative indices.
135///
136/// The output type of the indexing operation is an element or a slice respectively.
137///
138/// This trait enables the generic [`SliceIntExt::get_int`] method.
139///
140/// [`SliceIntExt::get_int`]: trait.Intex.html#fn.get_int
141pub trait IntSliceIndex<T: ?Sized>: sealed::SealedSliceIndex<T> {}
142
143/// Sealed traits for making `Intex` work as an index, without exposing too much.
144///
145/// ## Navigating the jungle of traits
146/// The main point here is to properly seal the traits. Parts of this are meant to be adopted by
147/// `core` at some point, this prevents some unwanted usage. Also note that user defined types
148/// convertible with `TryFromIntError` _should_ require slightly more ceremony.
149///
150/// So the `IntSliceIndex` is a parallel of `core::slice::SliceIndex` and inherited from the
151/// exposed `crate::IntSliceIndex`. It also contains the interface which we use internally. We
152/// can't define unstable methods, and methods would be inherited despite the hidden sealed trait.
153///
154/// ```
155/// mod sealed {
156///     pub trait Seal {
157///         fn can_be_observed(&self);
158///     }
159/// }
160///
161/// trait Public: sealed::Seal {}
162///
163/// fn with_public<T: Public>(t: &T) {
164///     t.can_be_observed();
165/// }
166/// ```
167///
168/// To work around this issue, we use two sealed traits with the same symbols. As neither can be
169/// named the necessary disambiguation can not be performed in a downstream crate.
170pub(crate) mod sealed {
171    use core::num::TryFromIntError;
172
173    /// A trait abstracting slice independent index behaviour, `ops::Index` can use on this.
174    ///
175    /// This is for two reasons. The panic message is improved by mentioning the original inputs.
176    /// But this requires the additional bounds of `Copy`, which is not available for `Range` due
177    /// to historical issues. By not exposing this we can always relax this later when, and if,
178    /// specialization becomes available to stable Rust.
179    pub trait IndexSealed {
180        /// Punts the `Copy` bound to the implementor.
181        fn copy(&self) -> Self;
182        #[cold]
183        fn panic_msg(limit: usize, idx: Self) -> !;
184    }
185
186    /// Provide one canonical conversion to an index.
187    ///
188    /// We use this converter to provide the methods of `IntSliceIndex` in the macro expanded
189    /// implementation.
190    pub trait IntoIntIndex {
191        type IntoIndex;
192        fn index(self) -> Result<Self::IntoIndex, TryFromIntError>;
193    }
194
195    /// Defines actual indexing on a potentially unsized type.
196    ///
197    /// This is sealed as well, as it contains the otherwise exposed `Index` item whose bounds we
198    /// may later want to adjust.
199    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    /// Seals the `Intex` extension trait.
210    /// The methods added there are intended to be like inherent methods on the respective
211    /// implementors which means additional implementors are not intended.
212    pub trait SealedSliceIntExt {}
213
214    /// Stops downstream from using the `IntSliceIndex` methods and associate type by having a
215    /// redundant pair of the same definitions. Methods do not have the same result type as this
216    /// does not influence type deduction and makes it clear that _we_ should never call them.
217    /// Hence, all methods provided here are actually unreachable.
218    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        // Safety: Propagates the requirements from the caller that this is a valid index.
270        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        // Safety: Propagates the requirements from the caller that this is a valid index.
281        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        // Safety: Propagates the requirements from the caller that this is a valid index.
310        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        // Safety: Propagates the requirements from the caller that this is a valid index.
321        unsafe { <T as sealed::IntSliceIndex<Self>>::get_unchecked_mut(idx, self) }
322    }
323}
324
325/// An indexing adaptor for `TryInto`.
326///
327/// This transparent wrapper allows any type to function as an index as long as it is fallibly
328/// convertible to a `usize`. An indexing operation is successful if the conversion succeeds and
329/// the resulting index is in bounds. Contrary to the simple integer types, the implementation of
330/// `get_unchecked` methods will _not_ unsafely assume that the conversion itself can't fail, only
331/// that the resulting index is in-bounds.
332///
333/// Separating this from the main `IndexType` solves a coherence problem that would occurs when
334/// instantiating it with ranges: The standard library is permitted to add new impls of
335/// `TryInto<usize>`, for example even for `Range<usize>`. Hence, these two impls would overlap
336/// but we would like the first to have another return type than the second. The indirection
337/// over this type means that our impls are only generic for `TryIndex<T>` instead and do not
338/// overlap.
339#[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        // Explicitly do __NOT__ make the conversion itself unchecked.
387        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        // Explicitly do __NOT__ make the conversion itself unchecked.
392        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/// An adaptor for `ops::Index` that uses this crate's `IntSliceIndex` instead of the standard one.
432///
433/// This struct can be used to index a slice with an arbitrary integer type, using the standard
434/// indexing syntax. It is also constructed by the [`Intex`] method exported in the crate root. The
435/// indexing operation will first try to convert the number of a `usize` index and then do the
436/// usual indexing.
437///
438/// [`Intex`]: ../fn.Intex.html
439///
440/// ```rust
441/// use index_ext::int::Intex;
442/// let val = [0u8; 2][Intex(1u32)];
443/// ```
444///
445/// This is a transparent wrapper.
446#[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
470// Core implementations for the basede types. We implement the `IntoIntIndex` trait for generic
471// types so we can reuse them in the concrete macro-derived impls of the sealed IntSliceIndex
472// trait.
473
474impl<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                // Safety: the caller promises that the index is valid.
531                Ok(idx) => unsafe { slice.get_unchecked(idx) },
532                // Safety: the caller promises that the index is valid.
533                // This implies that it is in-bounds of the `usize` type.
534                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                // Safety: the caller promises that the index is valid.
540                Ok(idx) => unsafe { slice.get_unchecked_mut(idx) },
541                // Safety: the caller promises that the index is valid.
542                // This implies that it is in-bounds of the `usize` type.
543                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                // Safety: the caller promises that the index is valid.
579                Ok(idx) => unsafe { slice.get_unchecked(idx) },
580                // Safety: the caller promises that the index is valid.
581                // This implies that it is in-bounds of the `usize` type.
582                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                // Safety: the caller promises that the index is valid.
588                Ok(idx) => unsafe { slice.get_unchecked_mut(idx) },
589                // Safety: the caller promises that the index is valid.
590                // This implies that it is in-bounds of the `usize` type.
591                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        // Clippy warns within here:
613        // > warning: question mark operator is useless here
614        //
615        // This is a 'false-positive' since this question mark not useless in all macro invocation.
616        // For `$t = usize` we have `Err=Infallible` instead.
617        #[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);