unchecked_index/
slice_impls.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

//!  This is a rather strange-looking workaround. The intention
//!  is to keep GetUnchecked/Mut out of scope, so that we can use the
//!  libcore SliceExt::get_unchecked/_mut methods.

use std::ops::{Range, RangeTo, RangeFrom, RangeFull};

use super::CheckIndex;

type Output<T, I> = <[T] as ::std::ops::Index<I>>::Output;

macro_rules! impl_for_slice {
    ($name:ident, $index_type:ty, $self_:ident, $index: ident, $assertion:expr) => {

        mod $name {
            use super::Output;
            #[allow(unused)]
            use std::ops::{Range, RangeTo, RangeFrom, RangeFull};

            #[inline]
            pub unsafe fn get<T>(s: &[T], index: $index_type) -> &Output<T, $index_type> {
                s.get_unchecked(index)
            }

            #[inline]
            pub unsafe fn getm<T>(s: &mut [T], index: $index_type) -> &mut Output<T, $index_type> {
                s.get_unchecked_mut(index)
            }
        }

        impl<T> CheckIndex<$index_type> for [T] {
            fn assert_indexable_with($self_: &Self, $index: &$index_type) {
                $assertion
            }
        }

        impl<T> super::GetUnchecked<$index_type> for [T] {
            type Output = Output<T, $index_type>;
            unsafe fn get_unchecked(&self, index: $index_type) -> &Self::Output {
                $name::get(self, index)
            }
        }

        impl<T> super::GetUncheckedMut<$index_type> for [T] {
            unsafe fn get_unchecked_mut(&mut self, index: $index_type) -> &mut Self::Output {
                $name::getm(self, index)
            }
        }
    }
}

impl_for_slice!(index, usize, self, index, {
    assert!(*index < self.len(),
            "assertion index < len failed: index out of bounds: \
            index = {}, len = {}",
            index, self.len())
});

impl_for_slice!(range, Range<usize>, self, index, {
  assert!(index.start <= index.end,
          "assertion start <= end failed: start = {}, end = {}, len = {}",
          index.start, index.end, self.len());
  assert!(index.end <= self.len(),
          "assertion end <= len failed: end = {}, len = {}",
          index.end, self.len());
});

impl_for_slice!(rangeto, RangeTo<usize>, self, index, {
  assert!(index.end <= self.len(),
          "assertion end <= len failed: end = {}, len = {}",
          index.end, self.len());
});

impl_for_slice!(rangefrom,RangeFrom<usize>, self, index, {
  assert!(index.start <= self.len(),
          "assertion start <= len failed: start = {}, len = {}",
          index.start, self.len());
});

impl_for_slice!(rangefull, RangeFull, self, _index, { });