1use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
2
3#[cfg(feature = "pui-core")]
4use crate::Id;
5use crate::PuiVec;
6
7#[cfg(feature = "pui-core")]
8use pui_core::OneShotIdentifier;
9
10use seal::Seal;
11#[forbid(missing_docs)]
12mod seal {
13 pub trait Seal: Sized {}
14}
15
16#[cold]
17#[inline(never)]
18fn index_fail() -> ! { panic!() }
19
20pub trait PuiVecIndex<I>: Seal {
22 type SliceIndex;
24
25 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool;
27
28 #[doc(hidden)]
29 fn slice_index(&self) -> Self::SliceIndex;
30}
31
32pub trait BuildPuiVecIndex<I>: PuiVecIndex<I> {
34 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self;
40}
41
42pub trait PuiVecAccess<T, I>: PuiVecIndex<I> {
44 type Output: ?Sized;
46
47 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output;
56
57 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output;
66
67 fn get<'a>(&self, vec: &'a PuiVec<T, I>) -> Option<&'a Self::Output> {
69 if self.contained_in(vec) {
70 Some(unsafe { self.get_unchecked(vec) })
71 } else {
72 None
73 }
74 }
75
76 fn get_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> Option<&'a mut Self::Output> {
78 if self.contained_in(vec) {
79 Some(unsafe { self.get_unchecked_mut(vec) })
80 } else {
81 None
82 }
83 }
84
85 fn index<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
87 if self.contained_in(vec) {
88 unsafe { self.get_unchecked(vec) }
89 } else {
90 index_fail()
91 }
92 }
93
94 fn index_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
96 if self.contained_in(vec) {
97 unsafe { self.get_unchecked_mut(vec) }
98 } else {
99 index_fail()
100 }
101 }
102}
103
104impl<Pi: ?Sized + Seal> Seal for &Pi {}
105impl<Pi: ?Sized + PuiVecIndex<I>, I> PuiVecIndex<I> for &Pi {
106 type SliceIndex = Pi::SliceIndex;
107
108 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { Pi::contained_in(self, vec) }
109
110 fn slice_index(&self) -> Self::SliceIndex { Pi::slice_index(self) }
111}
112
113impl<Pi: ?Sized + PuiVecAccess<T, I>, I, T> PuiVecAccess<T, I> for &Pi {
114 type Output = Pi::Output;
115
116 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output { Pi::get_unchecked(self, vec) }
117
118 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
119 Pi::get_unchecked_mut(self, vec)
120 }
121}
122
123impl<Pi: ?Sized + Seal> Seal for &mut Pi {}
124impl<Pi: ?Sized + PuiVecIndex<I>, I> PuiVecIndex<I> for &mut Pi {
125 type SliceIndex = Pi::SliceIndex;
126
127 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { Pi::contained_in(self, vec) }
128
129 fn slice_index(&self) -> Self::SliceIndex { Pi::slice_index(self) }
130}
131
132impl<Pi: ?Sized + PuiVecAccess<T, I>, I, T> PuiVecAccess<T, I> for &mut Pi {
133 type Output = Pi::Output;
134
135 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output { Pi::get_unchecked(self, vec) }
136
137 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
138 Pi::get_unchecked_mut(self, vec)
139 }
140}
141
142#[cold]
143#[inline(never)]
144#[cfg(feature = "pui-core")]
145fn not_owned() -> ! { panic!("Tried to use an id that isn't owned by the `PuiVec`") }
146
147#[cfg(feature = "pui-core")]
148impl<T> Seal for Id<T> {}
149#[cfg(feature = "pui-core")]
150#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
151impl<I: OneShotIdentifier> PuiVecIndex<I> for Id<I::Token> {
152 type SliceIndex = usize;
153
154 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool {
155 if vec.ident.owns_token(&self.token) {
156 true
157 } else {
158 not_owned()
159 }
160 }
161
162 fn slice_index(&self) -> Self::SliceIndex { self.index }
163}
164
165#[cfg(feature = "pui-core")]
166#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
167impl<I: OneShotIdentifier> BuildPuiVecIndex<I> for Id<I::Token> {
168 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self {
169 Id {
170 index: slice_index,
171 token: ident.token(),
172 }
173 }
174}
175
176#[cfg(feature = "pui-core")]
177#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
178impl<T, I: OneShotIdentifier> PuiVecAccess<T, I> for Id<I::Token> {
179 type Output = T;
180
181 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
182 vec.get_unchecked(PuiVecIndex::<I>::slice_index(self))
183 }
184
185 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
186 vec.get_unchecked_mut(PuiVecIndex::<I>::slice_index(self))
187 }
188}
189
190#[cfg(feature = "pui-core")]
191impl<T> Seal for RangeTo<Id<T>> {}
192#[cfg(feature = "pui-core")]
193#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
194impl<I: OneShotIdentifier> PuiVecIndex<I> for RangeTo<Id<I::Token>> {
195 type SliceIndex = RangeTo<usize>;
196
197 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool {
198 if vec.ident.owns_token(&self.end.token) {
199 true
200 } else {
201 not_owned()
202 }
203 }
204
205 fn slice_index(&self) -> Self::SliceIndex { ..self.end.index }
206}
207
208#[cfg(feature = "pui-core")]
209#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
210impl<I: OneShotIdentifier> BuildPuiVecIndex<I> for RangeTo<Id<I::Token>> {
211 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self {
212 ..Id {
213 index: slice_index.end,
214 token: ident.token(),
215 }
216 }
217}
218
219#[cfg(feature = "pui-core")]
220#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
221impl<T, I: OneShotIdentifier> PuiVecAccess<T, I> for RangeTo<Id<I::Token>> {
222 type Output = [T];
223
224 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
225 vec.get_unchecked(PuiVecIndex::<I>::slice_index(self))
226 }
227
228 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
229 vec.get_unchecked_mut(PuiVecIndex::<I>::slice_index(self))
230 }
231}
232
233#[cfg(feature = "pui-core")]
234impl<T> Seal for RangeFrom<Id<T>> {}
235#[cfg(feature = "pui-core")]
236#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
237impl<I: OneShotIdentifier> PuiVecIndex<I> for RangeFrom<Id<I::Token>> {
238 type SliceIndex = RangeFrom<usize>;
239
240 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool {
241 if vec.ident.owns_token(&self.start.token) {
242 true
243 } else {
244 not_owned()
245 }
246 }
247
248 fn slice_index(&self) -> Self::SliceIndex { self.start.index.. }
249}
250
251#[cfg(feature = "pui-core")]
252#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
253impl<I: OneShotIdentifier> BuildPuiVecIndex<I> for RangeFrom<Id<I::Token>> {
254 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self {
255 Id {
256 index: slice_index.start,
257 token: ident.token(),
258 }..
259 }
260}
261
262#[cfg(feature = "pui-core")]
263#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
264impl<T, I: OneShotIdentifier> PuiVecAccess<T, I> for RangeFrom<Id<I::Token>> {
265 type Output = [T];
266
267 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
268 vec.get_unchecked(PuiVecIndex::<I>::slice_index(self))
269 }
270
271 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
272 vec.get_unchecked_mut(PuiVecIndex::<I>::slice_index(self))
273 }
274}
275
276#[cfg(feature = "pui-core")]
277impl<T> Seal for RangeToInclusive<Id<T>> {}
278#[cfg(feature = "pui-core")]
279#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
280impl<I: OneShotIdentifier> PuiVecIndex<I> for RangeToInclusive<Id<I::Token>> {
281 type SliceIndex = RangeToInclusive<usize>;
282
283 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool {
284 if vec.ident.owns_token(&self.end.token) {
285 true
286 } else {
287 not_owned()
288 }
289 }
290
291 fn slice_index(&self) -> Self::SliceIndex { ..=self.end.index }
292}
293
294#[cfg(feature = "pui-core")]
295#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
296impl<I: OneShotIdentifier> BuildPuiVecIndex<I> for RangeToInclusive<Id<I::Token>> {
297 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self {
298 ..=Id {
299 index: slice_index.end,
300 token: ident.token(),
301 }
302 }
303}
304
305#[cfg(feature = "pui-core")]
306#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
307impl<T, I: OneShotIdentifier> PuiVecAccess<T, I> for RangeToInclusive<Id<I::Token>> {
308 type Output = [T];
309
310 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
311 vec.get_unchecked(PuiVecIndex::<I>::slice_index(self))
312 }
313
314 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
315 vec.get_unchecked_mut(PuiVecIndex::<I>::slice_index(self))
316 }
317}
318
319#[cfg(feature = "pui-core")]
320impl<T> Seal for Range<Id<T>> {}
321#[cfg(feature = "pui-core")]
322#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
323impl<I: OneShotIdentifier> PuiVecIndex<I> for Range<Id<I::Token>> {
324 type SliceIndex = Range<usize>;
325
326 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool {
327 if vec.ident.owns_token(&self.start.token) && vec.ident.owns_token(&self.end.token) {
328 true
329 } else {
330 not_owned()
331 }
332 }
333
334 fn slice_index(&self) -> Self::SliceIndex { self.start.index..self.end.index }
335}
336
337#[cfg(feature = "pui-core")]
338#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
339impl<I: OneShotIdentifier> BuildPuiVecIndex<I> for Range<Id<I::Token>> {
340 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self {
341 Id {
342 index: slice_index.start,
343 token: ident.token(),
344 }..Id {
345 index: slice_index.end,
346 token: ident.token(),
347 }
348 }
349}
350
351#[cfg(feature = "pui-core")]
352#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
353impl<T, I: OneShotIdentifier> PuiVecAccess<T, I> for Range<Id<I::Token>> {
354 type Output = [T];
355
356 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
357 vec.get_unchecked(PuiVecIndex::<I>::slice_index(self))
358 }
359
360 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
361 vec.get_unchecked_mut(PuiVecIndex::<I>::slice_index(self))
362 }
363}
364
365#[cfg(feature = "pui-core")]
366impl<T> Seal for RangeInclusive<Id<T>> {}
367#[cfg(feature = "pui-core")]
368#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
369impl<I: OneShotIdentifier> PuiVecIndex<I> for RangeInclusive<Id<I::Token>> {
370 type SliceIndex = RangeInclusive<usize>;
371
372 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool {
373 if vec.ident.owns_token(&self.start().token) && vec.ident.owns_token(&self.end().token) {
374 true
375 } else {
376 not_owned()
377 }
378 }
379
380 fn slice_index(&self) -> Self::SliceIndex { self.start().index..=self.end().index }
381}
382
383#[cfg(feature = "pui-core")]
384#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
385impl<I: OneShotIdentifier> BuildPuiVecIndex<I> for RangeInclusive<Id<I::Token>> {
386 unsafe fn new_unchecked(slice_index: Self::SliceIndex, ident: &I) -> Self {
387 Id {
388 index: *slice_index.start(),
389 token: ident.token(),
390 }..=Id {
391 index: *slice_index.end(),
392 token: ident.token(),
393 }
394 }
395}
396
397#[cfg(feature = "pui-core")]
398#[cfg_attr(docsrs, doc(cfg(feature = "pui")))]
399impl<T, I: OneShotIdentifier> PuiVecAccess<T, I> for RangeInclusive<Id<I::Token>> {
400 type Output = [T];
401
402 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
403 vec.get_unchecked(PuiVecIndex::<I>::slice_index(self))
404 }
405
406 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
407 vec.get_unchecked_mut(PuiVecIndex::<I>::slice_index(self))
408 }
409}
410
411impl Seal for usize {}
412impl<I> PuiVecIndex<I> for usize {
413 type SliceIndex = Self;
414
415 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(*self).is_some() }
416
417 fn slice_index(&self) -> Self::SliceIndex { *self }
418}
419
420impl<I> BuildPuiVecIndex<I> for usize {
421 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
422}
423
424impl<T, I> PuiVecAccess<T, I> for usize {
425 type Output = T;
426
427 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output { vec.vec.get_unchecked(*self) }
428
429 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
430 vec.vec.get_unchecked_mut(*self)
431 }
432}
433
434impl Seal for RangeFull {}
435impl<I> PuiVecIndex<I> for RangeFull {
436 type SliceIndex = Self;
437
438 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(*self).is_some() }
439
440 fn slice_index(&self) -> Self::SliceIndex { *self }
441}
442
443impl<I> BuildPuiVecIndex<I> for RangeFull {
444 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
445}
446
447impl<T, I> PuiVecAccess<T, I> for RangeFull {
448 type Output = [T];
449
450 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output { vec.vec.get_unchecked(*self) }
451
452 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
453 vec.vec.get_unchecked_mut(*self)
454 }
455}
456
457impl Seal for RangeTo<usize> {}
458impl<I> PuiVecIndex<I> for RangeTo<usize> {
459 type SliceIndex = Self;
460
461 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(*self).is_some() }
462
463 fn slice_index(&self) -> Self::SliceIndex { *self }
464}
465
466impl<I> BuildPuiVecIndex<I> for RangeTo<usize> {
467 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
468}
469
470impl<T, I> PuiVecAccess<T, I> for RangeTo<usize> {
471 type Output = [T];
472
473 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output { vec.vec.get_unchecked(*self) }
474
475 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
476 vec.vec.get_unchecked_mut(*self)
477 }
478}
479
480impl Seal for RangeFrom<usize> {}
481impl<I> PuiVecIndex<I> for RangeFrom<usize> {
482 type SliceIndex = Self;
483
484 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(self.clone()).is_some() }
485
486 fn slice_index(&self) -> Self::SliceIndex { self.clone() }
487}
488
489impl<I> BuildPuiVecIndex<I> for RangeFrom<usize> {
490 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
491}
492
493impl<T, I> PuiVecAccess<T, I> for RangeFrom<usize> {
494 type Output = [T];
495
496 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
497 vec.vec.get_unchecked(self.clone())
498 }
499
500 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
501 vec.vec.get_unchecked_mut(self.clone())
502 }
503}
504
505impl Seal for RangeToInclusive<usize> {}
506impl<I> PuiVecIndex<I> for RangeToInclusive<usize> {
507 type SliceIndex = Self;
508
509 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(*self).is_some() }
510
511 fn slice_index(&self) -> Self::SliceIndex { *self }
512}
513
514impl<I> BuildPuiVecIndex<I> for RangeToInclusive<usize> {
515 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
516}
517
518impl<T, I> PuiVecAccess<T, I> for RangeToInclusive<usize> {
519 type Output = [T];
520
521 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output { vec.vec.get_unchecked(*self) }
522
523 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
524 vec.vec.get_unchecked_mut(*self)
525 }
526}
527
528impl Seal for Range<usize> {}
529impl<I> PuiVecIndex<I> for Range<usize> {
530 type SliceIndex = Self;
531
532 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(self.clone()).is_some() }
533
534 fn slice_index(&self) -> Self::SliceIndex { self.clone() }
535}
536
537impl<I> BuildPuiVecIndex<I> for Range<usize> {
538 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
539}
540
541impl<T, I> PuiVecAccess<T, I> for Range<usize> {
542 type Output = [T];
543
544 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
545 vec.vec.get_unchecked(self.clone())
546 }
547
548 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
549 vec.vec.get_unchecked_mut(self.clone())
550 }
551}
552
553impl Seal for RangeInclusive<usize> {}
554impl<I> PuiVecIndex<I> for RangeInclusive<usize> {
555 type SliceIndex = Self;
556
557 fn contained_in<T>(&self, vec: &PuiVec<T, I>) -> bool { vec.vec.get(self.clone()).is_some() }
558
559 fn slice_index(&self) -> Self::SliceIndex { self.clone() }
560}
561
562impl<I> BuildPuiVecIndex<I> for RangeInclusive<usize> {
563 unsafe fn new_unchecked(slice_index: Self::SliceIndex, _: &I) -> Self { slice_index }
564}
565
566impl<T, I> PuiVecAccess<T, I> for RangeInclusive<usize> {
567 type Output = [T];
568
569 unsafe fn get_unchecked<'a>(&self, vec: &'a PuiVec<T, I>) -> &'a Self::Output {
570 vec.vec.get_unchecked(self.clone())
571 }
572
573 unsafe fn get_unchecked_mut<'a>(&self, vec: &'a mut PuiVec<T, I>) -> &'a mut Self::Output {
574 vec.vec.get_unchecked_mut(self.clone())
575 }
576}