1use {
2 crate::{
3 proof::{NonEmpty, Unknown},
4 Container, Index, IndexError,
5 },
6 core::{convert::TryFrom, fmt, hash::Hash, ops},
7};
8
9pub unsafe trait Idx: Copy + Ord + Hash
11where
12 Self: fmt::Debug,
13{
14 fn as_usize(self) -> usize;
16 fn from_usize(i: usize) -> Option<Self>;
17 fn zero() -> Self;
18 fn add(self, increment: usize) -> Self;
19 fn sub(self, decrement: usize) -> Self;
20}
21
22#[allow(non_snake_case)]
23macro_rules! impl_Idx {
24 ($($ty:ty),*$(,)?) => {
25 $(unsafe impl Idx for $ty {
26 fn as_usize(self) -> usize { self as usize } fn from_usize(i: usize) -> Option<Self> { Self::try_from(i).ok() }
28 fn zero() -> Self { 0 }
29 fn add(self, increment: usize) -> Self {
30 Self::from_usize(increment).and_then(|i| self.checked_add(i)).expect("increment")
32 }
33 fn sub(self, decrement: usize) -> Self {
34 self - Self::from_usize(decrement).expect("increment")
35 }
36 })*
37 };
38}
39
40impl_Idx! {
41 u8,
42 u16,
43 u32,
44 usize,
45}
46
47pub unsafe trait TrustedContainer {
52 type Item: ?Sized + TrustedItem<Self>;
53 type Slice: ?Sized;
54
55 fn unit_len(&self) -> usize;
57
58 unsafe fn get_unchecked(&self, i: usize) -> &Self::Item;
59 unsafe fn slice_unchecked(&self, r: ops::Range<usize>) -> &Self::Slice;
60}
61
62pub unsafe trait TrustedItem<Array: TrustedContainer<Item = Self> + ?Sized> {
64 type Unit;
65
66 fn vet<'id, I: Idx>(
71 idx: I,
72 container: &Container<'id, Array>,
73 ) -> Result<Index<'id, I, Unknown>, IndexError>;
74
75 fn after<'id, I: Idx>(
77 this: Index<'id, I, NonEmpty>,
78 container: &Container<'id, Array>,
79 ) -> Index<'id, I, Unknown>;
80
81 fn advance<'id, I: Idx>(
83 this: Index<'id, I, NonEmpty>,
84 container: &Container<'id, Array>,
85 ) -> Option<Index<'id, I, NonEmpty>>;
86}
87
88unsafe impl<T: TrustedContainer + ?Sized> TrustedContainer for &T {
89 type Item = T::Item;
90 type Slice = T::Slice;
91
92 fn unit_len(&self) -> usize {
93 T::unit_len(self)
94 }
95
96 unsafe fn get_unchecked(&self, i: usize) -> &Self::Item {
97 T::get_unchecked(self, i)
98 }
99
100 unsafe fn slice_unchecked(&self, r: ops::Range<usize>) -> &Self::Slice {
101 T::slice_unchecked(self, r)
102 }
103}
104
105unsafe impl<T> TrustedContainer for [T] {
106 type Item = T;
107 type Slice = [T];
108
109 fn unit_len(&self) -> usize {
110 self.len()
111 }
112
113 unsafe fn get_unchecked(&self, i: usize) -> &Self::Item {
114 debug_assert!(i < self.len());
115 self.get_unchecked(i)
116 }
117
118 unsafe fn slice_unchecked(&self, r: ops::Range<usize>) -> &Self::Slice {
119 debug_assert!(r.start <= self.len());
120 debug_assert!(r.end <= self.len());
121 debug_assert!(r.start <= r.end);
122 self.get_unchecked(r)
123 }
124}
125
126unsafe impl<T: TrustedItem<Array> + ?Sized, Array: TrustedContainer<Item = T> + ?Sized>
127 TrustedItem<&Array> for T
128{
129 type Unit = T::Unit;
130
131 fn vet<'id, I: Idx>(
132 idx: I,
133 container: &Container<'id, &Array>,
134 ) -> Result<Index<'id, I, Unknown>, IndexError> {
135 T::vet(idx, container.project())
136 }
137
138 fn after<'id, I: Idx>(
139 this: Index<'id, I, NonEmpty>,
140 container: &Container<'id, &Array>,
141 ) -> Index<'id, I, Unknown> {
142 T::after(this, container.project())
143 }
144
145 fn advance<'id, I: Idx>(
146 this: Index<'id, I, NonEmpty>,
147 container: &Container<'id, &Array>,
148 ) -> Option<Index<'id, I, NonEmpty>> {
149 T::advance(this, container.project())
150 }
151}
152
153unsafe impl<T> TrustedItem<[T]> for T {
154 type Unit = T;
155
156 fn vet<'id, I: Idx>(
157 idx: I,
158 container: &Container<'id, [T]>,
159 ) -> Result<Index<'id, I, Unknown>, IndexError> {
160 if idx.as_usize() <= container.unit_len() {
161 Ok(unsafe { Index::new(idx) })
162 } else {
163 Err(IndexError::OutOfBounds)
164 }
165 }
166
167 fn after<'id, I: Idx>(
168 this: Index<'id, I, NonEmpty>,
169 _: &Container<'id, [T]>,
170 ) -> Index<'id, I, Unknown> {
171 unsafe { Index::new(this.untrusted().add(1)) }
172 }
173
174 fn advance<'id, I: Idx>(
175 this: Index<'id, I, NonEmpty>,
176 container: &Container<'id, [T]>,
177 ) -> Option<Index<'id, I, NonEmpty>> {
178 container.vet(Self::after(this, container).untrusted()).ok()
179 }
180}
181
182#[cfg(feature = "std")]
183mod std_impls {
184 use super::*;
185 use std::{boxed::Box, vec::Vec};
186
187 #[cfg_attr(feature = "doc", doc(cfg(feature = "std")))]
188 unsafe impl<T: TrustedContainer + ?Sized> TrustedContainer for Box<T> {
189 type Item = T::Item;
190 type Slice = T::Slice;
191
192 fn unit_len(&self) -> usize {
193 T::unit_len(&self)
194 }
195
196 unsafe fn get_unchecked(&self, i: usize) -> &Self::Item {
197 T::get_unchecked(self, i)
198 }
199
200 unsafe fn slice_unchecked(&self, r: ops::Range<usize>) -> &Self::Slice {
201 T::slice_unchecked(self, r)
202 }
203 }
204
205 #[cfg_attr(feature = "doc", doc(cfg(feature = "std")))]
206 unsafe impl<T: TrustedItem<Array> + ?Sized, Array: TrustedContainer<Item = T> + ?Sized>
207 TrustedItem<Box<Array>> for T
208 {
209 type Unit = T::Unit;
210
211 fn vet<'id, I: Idx>(
212 idx: I,
213 container: &Container<'id, Box<Array>>,
214 ) -> Result<Index<'id, I, Unknown>, IndexError> {
215 T::vet(idx, container.project())
216 }
217
218 fn after<'id, I: Idx>(
219 this: Index<'id, I, NonEmpty>,
220 container: &Container<'id, Box<Array>>,
221 ) -> Index<'id, I, Unknown> {
222 T::after(this, container.project())
223 }
224
225 fn advance<'id, I: Idx>(
226 this: Index<'id, I, NonEmpty>,
227 container: &Container<'id, Box<Array>>,
228 ) -> Option<Index<'id, I, NonEmpty>> {
229 T::advance(this, container.project())
230 }
231 }
232
233 #[cfg_attr(feature = "doc", doc(cfg(feature = "std")))]
234 impl<'id, Array: TrustedContainer + ?Sized> Container<'id, Box<Array>> {
235 pub fn project(&self) -> &Container<'id, Array> {
236 unsafe { &*(&**self.untrusted() as *const Array as *const Container<'id, Array>) }
237 }
238 }
239
240 #[cfg_attr(feature = "doc", doc(cfg(feature = "std")))]
241 unsafe impl<T> TrustedContainer for Vec<T> {
242 type Item = T;
243 type Slice = [T];
244
245 fn unit_len(&self) -> usize {
246 self.len()
247 }
248
249 unsafe fn get_unchecked(&self, i: usize) -> &Self::Item {
250 <[T]>::get_unchecked(self, i)
251 }
252
253 unsafe fn slice_unchecked(&self, r: ops::Range<usize>) -> &Self::Slice {
254 <[T]>::slice_unchecked(self, r)
255 }
256 }
257
258 #[cfg_attr(feature = "doc", doc(cfg(feature = "std")))]
259 unsafe impl<T: TrustedItem<[T]>> TrustedItem<Vec<T>> for T {
260 type Unit = T::Unit;
261
262 fn vet<'id, I: Idx>(
263 idx: I,
264 container: &Container<'id, Vec<T>>,
265 ) -> Result<Index<'id, I, Unknown>, IndexError> {
266 T::vet(idx, container.project())
267 }
268
269 fn after<'id, I: Idx>(
270 this: Index<'id, I, NonEmpty>,
271 container: &Container<'id, Vec<T>>,
272 ) -> Index<'id, I, Unknown> {
273 T::after(this, container.project())
274 }
275
276 fn advance<'id, I: Idx>(
277 this: Index<'id, I, NonEmpty>,
278 container: &Container<'id, Vec<T>>,
279 ) -> Option<Index<'id, I, NonEmpty>> {
280 T::advance(this, container.project())
281 }
282 }
283
284 #[cfg_attr(feature = "doc", doc(cfg(feature = "std")))]
285 impl<'id, T> Container<'id, Vec<T>> {
286 pub fn project(&self) -> &Container<'id, [T]> {
287 unsafe { &*(&**self.untrusted() as *const [T] as *const Container<'id, [T]>) }
288 }
289 }
290}