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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//! Variants of `ops` traits that work with raw references.

use ::ptr_meta::metadata;

use crate::{Mut, Ref};

/// A variant of `Deref` that works with raw references.
pub trait DerefRaw {
    /// The resulting type after dereferencing.
    type Target: ?Sized;

    /// Dereferences the value.
    fn deref_raw(this: Ref<'_, Self>) -> Ref<'_, Self::Target>;
}

/// A variant of `DerefMut` that works with raw references.
pub trait DerefMutRaw: DerefRaw {
    /// Mutably dereferences the value.
    fn deref_mut_raw(this: Mut<'_, Self>) -> Mut<'_, Self::Target>;
}

/// A variant of `Index` that works with raw references.
pub trait IndexRaw<Idx> {
    /// The returned type after indexing.
    type Output: ?Sized;

    /// Performs the indexing (`container[index]`) operation.
    ///
    /// # Panics
    ///
    /// May panic if the index is out of bounds.
    fn index_raw(this: Ref<'_, Self>, index: Idx) -> Ref<'_, Self::Output>;

    /// Performs the indexing (`container[index]`) operation without performing
    /// bounds checking
    ///
    /// # Safety
    ///
    /// `index` must be in bounds for `this`.
    unsafe fn index_raw_unchecked(
        this: Ref<'_, Self>,
        index: Idx,
    ) -> Ref<'_, Self::Output>;
}

/// A variant of `IndexMut` that works with raw references.
pub trait IndexMutRaw<Idx>: IndexRaw<Idx> {
    /// Performs the mutable indexing (`container[index]`) operation.
    ///
    /// # Panics
    ///
    /// May panic if the index is out of bounds.
    fn index_mut_raw(this: Mut<'_, Self>, index: Idx) -> Mut<'_, Self::Output>;

    /// Performs the mutable indexing (`container[index]`) operation without
    /// performing bounds checking
    ///
    /// # Safety
    ///
    /// `index` must be in bounds for `this`.
    unsafe fn index_mut_raw_unchecked(
        this: Mut<'_, Self>,
        index: Idx,
    ) -> Mut<'_, Self::Output>;
}

impl<T, const N: usize> IndexRaw<usize> for [T; N] {
    type Output = T;

    fn index_raw(this: Ref<'_, Self>, index: usize) -> Ref<'_, Self::Output> {
        assert!(index < N);
        // SAFETY: We asserted that `index` is less than `N` and so it in
        // bounds.
        unsafe { Self::index_raw_unchecked(this, index) }
    }

    unsafe fn index_raw_unchecked(
        this: Ref<'_, Self>,
        index: usize,
    ) -> Ref<'_, Self::Output> {
        // SAFETY: This pointer add is safe because the pointer is guaranteed to
        // be to the first `T` in an array of `N` consecutive `T`, and the
        // resulting pointer must be in-bounds because the caller has guaranteed
        // that `index` is less than `N`.
        let ptr = unsafe { this.as_ptr().cast::<T>().add(index) };
        // SAFETY: The offset pointer is to an element of the original array,
        // and so must be non-null, properly aligned, valid for reads, and
        // initialized. It has the same shared aliasing as the `Ref` it is
        // derived from, and so must not alias any other mutable references for
        // `'_`.
        unsafe { Ref::new_unchecked(ptr) }
    }
}

impl<T, const N: usize> IndexMutRaw<usize> for [T; N] {
    fn index_mut_raw(
        this: Mut<'_, Self>,
        index: usize,
    ) -> Mut<'_, Self::Output> {
        assert!(index < N);
        // SAFETY: We asserted that `index` is less than `N` and so is in
        // bounds.
        unsafe { Self::index_mut_raw_unchecked(this, index) }
    }

    unsafe fn index_mut_raw_unchecked(
        this: Mut<'_, Self>,
        index: usize,
    ) -> Mut<'_, Self::Output> {
        // SAFETY: This pointer add is safe because the pointer is guaranteed to
        // be to the first `T` in an array of `N` consecutive `T`, and the
        // resulting pointer must be in-bounds because the caller has guaranteed
        // that `index` is less than `N`.
        let ptr = unsafe { this.as_ptr().cast::<T>().add(index) };
        // SAFETY: The offset pointer is to an element of the original array,
        // and so must be non-null, properly aligned, valid for reads, and
        // initialized. It has the same mutable aliasing as the `Mut` it is
        // derived from, and so must not alias any other accessible references
        // for `'_`.
        unsafe { Mut::new_unchecked(ptr) }
    }
}

impl<T> IndexRaw<usize> for [T] {
    type Output = T;

    fn index_raw(this: Ref<'_, Self>, index: usize) -> Ref<'_, Self::Output> {
        let slice_ptr = this.as_ptr();
        let len = metadata(slice_ptr);
        assert!(index < len, "index out of bounds");
        // SAFETY: We asserted that `index` is less than `len` and so it in
        // bounds.
        unsafe { Self::index_raw_unchecked(this, index) }
    }

    unsafe fn index_raw_unchecked(
        this: Ref<'_, Self>,
        index: usize,
    ) -> Ref<'_, Self::Output> {
        let slice_ptr = this.as_ptr();
        // SAFETY: This pointer add is safe because the pointer is guaranteed to
        // be to the first `T` in a slice of `len` consecutive `T`, and the
        // resulting pointer must be in-bounds because the caller has guaranteed
        // that `index` is less than `len`.
        let ptr = unsafe { slice_ptr.cast::<T>().add(index) };
        // SAFETY: The offset pointer is to an element of the original slice,
        // and so must be non-null, properly aligned, valid for reads, and
        // initialized. It has the same shared aliasing as the `Ref` it is
        // derived from, and so must not alias any other mutable references for
        // `'_`.
        unsafe { Ref::new_unchecked(ptr) }
    }
}

impl<T> IndexMutRaw<usize> for [T] {
    fn index_mut_raw(
        this: Mut<'_, Self>,
        index: usize,
    ) -> Mut<'_, Self::Output> {
        let slice_ptr = this.as_ptr();
        let len = metadata(slice_ptr);
        assert!(index < len, "index out of bounds");
        // SAFETY: We asserted that `index` is less than `len` and so is in
        // bounds.
        unsafe { Self::index_mut_raw_unchecked(this, index) }
    }

    unsafe fn index_mut_raw_unchecked(
        this: Mut<'_, Self>,
        index: usize,
    ) -> Mut<'_, Self::Output> {
        let slice_ptr = this.as_ptr();
        // SAFETY: This pointer add is safe because the pointer is guaranteed to
        // be to the first `T` in a slice of `len` consecutive `T`, and the
        // resulting pointer must be in-bounds because the caller has guaranteed
        // that `index` is less than `len`.
        let ptr = unsafe { slice_ptr.cast::<T>().add(index) };
        // SAFETY: The offset pointer is to an element of the original slice,
        // and so must be non-null, properly aligned, valid for reads, and
        // initialized. It has the same mutable aliasing as the `Mut` it is
        // derived from, and so must not alias any other accessible references
        // for `'_`.
        unsafe { Mut::new_unchecked(ptr) }
    }
}