1#[cfg(test)]
2mod tests;
3
4#[macro_export]
5macro_rules! implement_generic_index {
6 ($index:ident, $optional_index:ident) => {
7 #[cfg_attr(
8 feature = "zerocopy",
9 derive(
10 zerocopy::FromBytes,
11 zerocopy::IntoBytes,
12 zerocopy::KnownLayout,
13 zerocopy::Immutable,
14 zerocopy::Unaligned,
15 )
16 )]
17 #[repr(transparent)]
18 struct $index<IndexType>(IndexType);
19
20 #[cfg_attr(
21 feature = "zerocopy",
22 derive(
23 zerocopy::FromBytes,
24 zerocopy::IntoBytes,
25 zerocopy::KnownLayout,
26 zerocopy::Immutable,
27 zerocopy::Unaligned,
28 )
29 )]
30 #[repr(transparent)]
31 struct $optional_index<IndexType>(IndexType);
32
33 implement_generic_index!($index, $optional_index, __inner__);
34 };
35
36 (pub $index:ident, pub $optional_index:ident) => {
37 #[cfg_attr(
38 feature = "zerocopy",
39 derive(
40 zerocopy::FromBytes,
41 zerocopy::IntoBytes,
42 zerocopy::KnownLayout,
43 zerocopy::Immutable,
44 zerocopy::Unaligned,
45 )
46 )]
47 #[repr(transparent)]
48 pub struct $index<IndexType>(IndexType);
49
50 #[cfg_attr(
51 feature = "zerocopy",
52 derive(
53 zerocopy::FromBytes,
54 zerocopy::IntoBytes,
55 zerocopy::KnownLayout,
56 zerocopy::Immutable,
57 zerocopy::Unaligned,
58 )
59 )]
60 #[repr(transparent)]
61 pub struct $optional_index<IndexType>(IndexType);
62
63 implement_generic_index!($index, $optional_index, __inner__);
64 };
65
66 (pub(crate) $index:ident, pub(crate) $optional_index:ident) => {
67 #[cfg_attr(
68 feature = "zerocopy",
69 derive(
70 zerocopy::FromBytes,
71 zerocopy::IntoBytes,
72 zerocopy::KnownLayout,
73 zerocopy::Immutable,
74 zerocopy::Unaligned,
75 )
76 )]
77 #[repr(transparent)]
78 pub(crate) struct $index<IndexType>(IndexType);
79
80 #[cfg_attr(
81 feature = "zerocopy",
82 derive(
83 zerocopy::FromBytes,
84 zerocopy::IntoBytes,
85 zerocopy::KnownLayout,
86 zerocopy::Immutable,
87 zerocopy::Unaligned,
88 )
89 )]
90 #[repr(transparent)]
91 pub(crate) struct $optional_index<IndexType>(IndexType);
92
93 implement_generic_index!($index, $optional_index, __inner__);
94 };
95
96 (pub(super) $index:ident, pub(super) $optional_index:ident) => {
97 #[cfg_attr(
98 feature = "zerocopy",
99 derive(
100 zerocopy::FromBytes,
101 zerocopy::IntoBytes,
102 zerocopy::KnownLayout,
103 zerocopy::Immutable,
104 zerocopy::Unaligned,
105 )
106 )]
107 #[repr(transparent)]
108 pub(super) struct $index<IndexType>(IndexType);
109
110 #[cfg_attr(
111 feature = "zerocopy",
112 derive(
113 zerocopy::FromBytes,
114 zerocopy::IntoBytes,
115 zerocopy::KnownLayout,
116 zerocopy::Immutable,
117 zerocopy::Unaligned,
118 )
119 )]
120 #[repr(transparent)]
121 pub(super) struct $optional_index<IndexType>(IndexType);
122
123 implement_generic_index!($index, $optional_index, __inner__);
124 };
125
126 (pub(in $index_visibility:path) $index:ident, pub(in $optional_index_visibility:path) $optional_index:ident) => {
127 #[cfg_attr(
128 feature = "zerocopy",
129 derive(
130 zerocopy::FromBytes,
131 zerocopy::IntoBytes,
132 zerocopy::KnownLayout,
133 zerocopy::Immutable,
134 zerocopy::Unaligned,
135 )
136 )]
137 #[repr(transparent)]
138 pub(in $index_visibility) struct $index<IndexType>(IndexType);
139
140 #[cfg_attr(
141 feature = "zerocopy",
142 derive(
143 zerocopy::FromBytes,
144 zerocopy::IntoBytes,
145 zerocopy::KnownLayout,
146 zerocopy::Immutable,
147 zerocopy::Unaligned,
148 )
149 )]
150 #[repr(transparent)]
151 pub(in $optional_index_visibility) struct $optional_index<IndexType>(IndexType);
152
153 implement_generic_index!($index, $optional_index, __inner__);
154 };
155
156 ($index:ident, $optional_index:ident, __inner__) => {
157 impl<IndexType> $index<IndexType> {
162 #[allow(dead_code)]
163 pub fn new(value: IndexType) -> Self
164 where
165 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
166 {
167 assert_ne!(value, IndexType::max_value());
168 Self(value)
169 }
170
171 #[allow(dead_code)]
172 pub fn from_usize(value: usize) -> Self
173 where
174 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>,
175 {
176 Self::new(
177 value
178 .try_into()
179 .ok()
180 .expect("index conversion from usize failed"),
181 )
182 }
183
184 #[allow(dead_code)]
185 pub fn into_usize(self) -> usize
186 where
187 IndexType: TryInto<usize>,
188 {
189 self.0
190 .try_into()
191 .ok()
192 .expect("index conversion to usize failed")
193 }
194
195 #[allow(dead_code)]
196 pub fn from_raw(value: IndexType) -> Self
197 where
198 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
199 {
200 Self::new(value)
201 }
202
203 #[allow(dead_code)]
204 pub fn into_raw(self) -> IndexType {
205 self.0
206 }
207 }
208
209 impl<IndexType> $optional_index<IndexType> {
214 #[allow(dead_code)]
215 pub fn new_some(value: IndexType) -> Self
216 where
217 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
218 {
219 assert_ne!(value, IndexType::max_value());
220 Self(value)
221 }
222
223 #[allow(dead_code)]
224 pub fn new_none() -> Self
225 where
226 IndexType: num_traits::bounds::UpperBounded,
227 {
228 Self(IndexType::max_value())
229 }
230
231 #[allow(dead_code)]
232 pub fn from_option(option: Option<$index<IndexType>>) -> Self
233 where
234 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
235 {
236 Self::from(option)
237 }
238
239 #[allow(dead_code)]
240 pub fn into_option(self) -> Option<$index<IndexType>>
241 where
242 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
243 {
244 self.into()
245 }
246
247 #[allow(dead_code)]
248 pub fn expect(self, message: &str) -> $index<IndexType>
249 where
250 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
251 {
252 self.into_option().expect(message)
253 }
254
255 #[allow(dead_code)]
256 pub fn unwrap(self) -> $index<IndexType>
257 where
258 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
259 {
260 self.into_option().unwrap()
261 }
262
263 #[allow(dead_code)]
264 pub fn unwrap_or(self, default: $index<IndexType>) -> $index<IndexType>
265 where
266 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
267 {
268 self.into_option().unwrap_or(default)
269 }
270
271 #[allow(dead_code)]
272 pub fn unwrap_or_else(
273 self,
274 default: impl FnOnce() -> $index<IndexType>,
275 ) -> $index<IndexType>
276 where
277 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
278 {
279 self.into_option().unwrap_or_else(default)
280 }
281
282 #[allow(dead_code)]
283 pub unsafe fn unwrap_unchecked(self) -> $index<IndexType>
284 where
285 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
286 {
287 unsafe { self.into_option().unwrap_unchecked() }
288 }
289
290 #[allow(dead_code)]
291 pub fn from_usize(value: usize) -> Self
292 where
293 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>,
294 {
295 Self::new_some(
296 value
297 .try_into()
298 .ok()
299 .expect("index conversion from usize failed"),
300 )
301 }
302
303 #[allow(dead_code)]
304 pub fn from_option_usize(value: Option<usize>) -> Self
305 where
306 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>,
307 {
308 if let Some(value) = value {
309 Self::new_some(
310 value
311 .try_into()
312 .ok()
313 .expect("index conversion from usize failed"),
314 )
315 } else {
316 Self::new_none()
317 }
318 }
319
320 #[allow(dead_code)]
321 pub fn into_usize(self) -> Option<usize>
322 where
323 IndexType: num_traits::bounds::UpperBounded + Eq + TryInto<usize>,
324 {
325 if self.is_some() {
326 Some(
327 self.0
328 .try_into()
329 .ok()
330 .expect("index conversion to usize failed"),
331 )
332 } else {
333 None
334 }
335 }
336
337 #[allow(dead_code)]
338 pub fn from_raw(value: Option<IndexType>) -> Self
339 where
340 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
341 {
342 if let Some(value) = value {
343 Self::new_some(value)
344 } else {
345 Self::new_none()
346 }
347 }
348
349 #[allow(dead_code)]
350 pub fn into_raw(self) -> Option<IndexType>
351 where
352 IndexType: num_traits::bounds::UpperBounded + Eq,
353 {
354 if self.is_some() { Some(self.0) } else { None }
355 }
356
357 #[allow(dead_code)]
358 pub fn is_some(&self) -> bool
359 where
360 IndexType: num_traits::bounds::UpperBounded + Eq,
361 {
362 self.0 != IndexType::max_value()
363 }
364
365 #[allow(dead_code)]
366 pub fn is_none(&self) -> bool
367 where
368 IndexType: num_traits::bounds::UpperBounded + Eq,
369 {
370 self.0 == IndexType::max_value()
371 }
372 }
373
374 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug>
379 From<Option<$index<IndexType>>> for $optional_index<IndexType>
380 {
381 fn from(index: Option<$index<IndexType>>) -> Self {
382 if let Some(index) = index {
383 Self::new_some(index.0)
384 } else {
385 Self::new_none()
386 }
387 }
388 }
389
390 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug>
391 From<$index<IndexType>> for $optional_index<IndexType>
392 {
393 fn from(index: $index<IndexType>) -> Self {
394 Self::new_some(index.0)
395 }
396 }
397
398 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug>
399 From<$optional_index<IndexType>> for Option<$index<IndexType>>
400 {
401 fn from(optional_index: $optional_index<IndexType>) -> Self {
402 if optional_index.is_some() {
403 Some($index::new(optional_index.0))
404 } else {
405 None
406 }
407 }
408 }
409
410 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>>
415 From<usize> for $index<IndexType>
416 {
417 fn from(value: usize) -> Self {
418 Self::new(
419 value
420 .try_into()
421 .ok()
422 .expect("index conversion from usize failed"),
423 )
424 }
425 }
426
427 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>>
428 From<usize> for $optional_index<IndexType>
429 {
430 fn from(value: usize) -> Self {
431 Self::new_some(
432 value
433 .try_into()
434 .ok()
435 .expect("index conversion from usize failed"),
436 )
437 }
438 }
439
440 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>>
441 From<Option<usize>> for $optional_index<IndexType>
442 {
443 fn from(value: Option<usize>) -> Self {
444 if let Some(value) = value {
445 Self::new_some(
446 value
447 .try_into()
448 .ok()
449 .expect("index conversion from usize failed"),
450 )
451 } else {
452 Self::new_none()
453 }
454 }
455 }
456
457 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryInto<usize>>
458 From<$index<IndexType>> for usize
459 {
460 fn from(value: $index<IndexType>) -> Self {
461 value
462 .0
463 .try_into()
464 .ok()
465 .expect("index conversion from usize failed")
466 }
467 }
468
469 impl<IndexType: num_traits::bounds::UpperBounded + Eq + TryInto<usize>>
470 From<$optional_index<IndexType>> for Option<usize>
471 {
472 fn from(index: $optional_index<IndexType>) -> Self {
473 if index.is_some() {
474 Some(
475 index
476 .0
477 .try_into()
478 .ok()
479 .expect("index conversion to usize failed"),
480 )
481 } else {
482 None
483 }
484 }
485 }
486
487 impl<IndexType: std::fmt::Debug> std::fmt::Debug for $index<IndexType> {
492 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
493 write!(f, "{}({:?})", stringify!($index), self.0)
494 }
495 }
496
497 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug> std::fmt::Debug
498 for $optional_index<IndexType>
499 {
500 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
501 if self.is_some() {
502 write!(f, "{}({:?})", stringify!($optional_index), self.0)
503 } else {
504 write!(f, "{}(None)", stringify!($optional_index))
505 }
506 }
507 }
508
509 impl<IndexType: std::fmt::Display> std::fmt::Display for $index<IndexType> {
510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
511 write!(f, "{}", self.0)
512 }
513 }
514
515 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Display> std::fmt::Display
516 for $optional_index<IndexType>
517 {
518 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
519 if self.is_some() {
520 write!(f, "{}", self.0)
521 } else {
522 write!(f, "None")
523 }
524 }
525 }
526
527 impl<IndexType: Clone> Clone for $index<IndexType> {
532 fn clone(&self) -> Self {
533 Self(self.0.clone())
534 }
535 }
536
537 impl<IndexType: Clone> Clone for $optional_index<IndexType> {
538 fn clone(&self) -> Self {
539 Self(self.0.clone())
540 }
541 }
542
543 impl<IndexType: Copy> Copy for $index<IndexType> {}
544
545 impl<IndexType: Copy> Copy for $optional_index<IndexType> {}
546
547 impl<IndexType: PartialEq> PartialEq for $index<IndexType> {
552 fn eq(&self, other: &Self) -> bool {
553 self.0.eq(&other.0)
554 }
555 }
556
557 impl<IndexType: PartialEq> PartialEq for $optional_index<IndexType> {
558 fn eq(&self, other: &Self) -> bool {
559 self.0.eq(&other.0)
560 }
561 }
562
563 impl<IndexType: Eq> Eq for $index<IndexType> {}
564
565 impl<IndexType: Eq> Eq for $optional_index<IndexType> {}
566
567 impl<IndexType: PartialOrd> PartialOrd for $index<IndexType> {
572 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
573 self.0.partial_cmp(&other.0)
574 }
575 }
576
577 impl<IndexType: PartialOrd> PartialOrd for $optional_index<IndexType> {
578 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
579 self.0.partial_cmp(&other.0)
580 }
581 }
582
583 impl<IndexType: Ord> Ord for $index<IndexType> {
584 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
585 self.0.cmp(&other.0)
586 }
587 }
588
589 impl<IndexType: Ord> Ord for $optional_index<IndexType> {
590 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
591 self.0.cmp(&other.0)
592 }
593 }
594
595 impl<IndexType: std::hash::Hash> std::hash::Hash for $index<IndexType> {
600 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
601 self.0.hash(state);
602 }
603 }
604
605 impl<IndexType: std::hash::Hash> std::hash::Hash for $optional_index<IndexType> {
606 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
607 self.0.hash(state);
608 }
609 }
610 };
611}
612
613#[macro_export]
614macro_rules! implement_fixed_index {
615 ($index:ident, $optional_index:ident, $index_type:ty) => {
616 #[cfg_attr(
617 feature = "zerocopy",
618 derive(
619 zerocopy::FromBytes,
620 zerocopy::IntoBytes,
621 zerocopy::KnownLayout,
622 zerocopy::Immutable,
623 )
624 )]
625 #[repr(transparent)]
626 struct $index($index_type);
627
628 #[cfg_attr(
629 feature = "zerocopy",
630 derive(
631 zerocopy::FromBytes,
632 zerocopy::IntoBytes,
633 zerocopy::KnownLayout,
634 zerocopy::Immutable,
635 )
636 )]
637 #[repr(transparent)]
638 struct $optional_index($index_type);
639
640 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
641 };
642
643 (pub $index:ident, pub $optional_index:ident, $index_type:ty) => {
644 #[cfg_attr(
645 feature = "zerocopy",
646 derive(
647 zerocopy::FromBytes,
648 zerocopy::IntoBytes,
649 zerocopy::KnownLayout,
650 zerocopy::Immutable,
651 )
652 )]
653 pub struct $index($index_type);
654
655 #[cfg_attr(
656 feature = "zerocopy",
657 derive(
658 zerocopy::FromBytes,
659 zerocopy::IntoBytes,
660 zerocopy::KnownLayout,
661 zerocopy::Immutable,
662 )
663 )]
664 pub struct $optional_index($index_type);
665
666 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
667 };
668
669 (pub(crate) $index:ident, pub(crate) $optional_index:ident, $index_type:ty) => {
670 #[cfg_attr(
671 feature = "zerocopy",
672 derive(
673 zerocopy::FromBytes,
674 zerocopy::IntoBytes,
675 zerocopy::KnownLayout,
676 zerocopy::Immutable,
677 )
678 )]
679 pub(crate) struct $index($index_type);
680
681 #[cfg_attr(
682 feature = "zerocopy",
683 derive(
684 zerocopy::FromBytes,
685 zerocopy::IntoBytes,
686 zerocopy::KnownLayout,
687 zerocopy::Immutable,
688 )
689 )]
690 pub(crate) struct $optional_index($index_type);
691
692 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
693 };
694
695 (pub(super) $index:ident, pub(super) $optional_index:ident, $index_type:ty) => {
696 #[cfg_attr(
697 feature = "zerocopy",
698 derive(
699 zerocopy::FromBytes,
700 zerocopy::IntoBytes,
701 zerocopy::KnownLayout,
702 zerocopy::Immutable,
703 )
704 )]
705 pub(super) struct $index($index_type);
706
707 #[cfg_attr(
708 feature = "zerocopy",
709 derive(
710 zerocopy::FromBytes,
711 zerocopy::IntoBytes,
712 zerocopy::KnownLayout,
713 zerocopy::Immutable,
714 )
715 )]
716 pub(super) struct $optional_index($index_type);
717
718 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
719 };
720
721 (pub(in $index_visibility:path) $index:ident, pub(in $optional_index_visibility:path) $optional_index:ident, $index_type:ty) => {
722 #[cfg_attr(
723 feature = "zerocopy",
724 derive(
725 zerocopy::FromBytes,
726 zerocopy::IntoBytes,
727 zerocopy::KnownLayout,
728 zerocopy::Immutable,
729 )
730 )]
731 pub(in $index_visibility) struct $index($index_type);
732
733 #[cfg_attr(
734 feature = "zerocopy",
735 derive(
736 zerocopy::FromBytes,
737 zerocopy::IntoBytes,
738 zerocopy::KnownLayout,
739 zerocopy::Immutable,
740 )
741 )]
742 pub(in $optional_index_visibility) struct $optional_index($index_type);
743
744 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
745 };
746
747 ($index:ident, $optional_index:ident, $index_type:ty, __inner__) => {
748 impl $index {
753 #[allow(dead_code)]
754 pub fn new(value: $index_type) -> Self {
755 assert_ne!(value, num_traits::bounds::UpperBounded::max_value());
756 Self(value)
757 }
758
759 #[allow(dead_code)]
760 pub fn from_usize(value: usize) -> Self {
761 Self::new(
762 value
763 .try_into()
764 .ok()
765 .expect("index conversion from usize failed"),
766 )
767 }
768
769 #[allow(dead_code)]
770 pub fn into_usize(self) -> usize {
771 self.0
772 .try_into()
773 .ok()
774 .expect("index conversion to usize failed")
775 }
776
777 #[allow(dead_code)]
778 pub fn from_raw(value: $index_type) -> Self {
779 Self::new(value)
780 }
781
782 #[allow(dead_code)]
783 pub fn into_raw(self) -> $index_type {
784 self.0
785 }
786 }
787
788 impl $optional_index {
793 #[allow(dead_code)]
794 pub fn new_some(value: $index_type) -> Self {
795 assert_ne!(value, num_traits::bounds::UpperBounded::max_value());
796 Self(value)
797 }
798
799 #[allow(dead_code)]
800 pub fn new_none() -> Self {
801 Self(num_traits::bounds::UpperBounded::max_value())
802 }
803
804 #[allow(dead_code)]
805 pub fn from_option(option: Option<$index>) -> Self {
806 Self::from(option)
807 }
808
809 #[allow(dead_code)]
810 pub fn into_option(self) -> Option<$index> {
811 self.into()
812 }
813
814 #[allow(dead_code)]
815 pub fn expect(self, message: &str) -> $index {
816 self.into_option().expect(message)
817 }
818
819 #[allow(dead_code)]
820 pub fn unwrap(self) -> $index {
821 self.into_option().unwrap()
822 }
823
824 #[allow(dead_code)]
825 pub fn unwrap_or(self, default: $index) -> $index {
826 self.into_option().unwrap_or(default)
827 }
828
829 #[allow(dead_code)]
830 pub fn unwrap_or_else(self, default: impl FnOnce() -> $index) -> $index {
831 self.into_option().unwrap_or_else(default)
832 }
833
834 #[allow(dead_code)]
835 pub unsafe fn unwrap_unchecked(self) -> $index {
836 unsafe { self.into_option().unwrap_unchecked() }
837 }
838
839 #[allow(dead_code)]
840 pub fn from_usize(value: usize) -> Self {
841 Self::new_some(
842 value
843 .try_into()
844 .ok()
845 .expect("index conversion from usize failed"),
846 )
847 }
848
849 #[allow(dead_code)]
850 pub fn from_option_usize(value: Option<usize>) -> Self {
851 if let Some(value) = value {
852 Self::new_some(
853 value
854 .try_into()
855 .ok()
856 .expect("index conversion from usize failed"),
857 )
858 } else {
859 Self::new_none()
860 }
861 }
862
863 #[allow(dead_code)]
864 pub fn into_usize(self) -> Option<usize> {
865 if self.is_some() {
866 Some(
867 self.0
868 .try_into()
869 .ok()
870 .expect("index conversion to usize failed"),
871 )
872 } else {
873 None
874 }
875 }
876
877 #[allow(dead_code)]
878 pub fn from_raw(value: Option<$index_type>) -> Self {
879 if let Some(value) = value {
880 Self::new_some(value)
881 } else {
882 Self::new_none()
883 }
884 }
885
886 #[allow(dead_code)]
887 pub fn into_raw(self) -> Option<$index_type> {
888 if self.is_some() { Some(self.0) } else { None }
889 }
890
891 #[allow(dead_code)]
892 pub fn is_some(&self) -> bool {
893 self.0 != num_traits::bounds::UpperBounded::max_value()
894 }
895
896 #[allow(dead_code)]
897 pub fn is_none(&self) -> bool {
898 self.0 == num_traits::bounds::UpperBounded::max_value()
899 }
900 }
901
902 impl From<Option<$index>> for $optional_index {
907 fn from(index: Option<$index>) -> Self {
908 if let Some(index) = index {
909 Self::new_some(index.0)
910 } else {
911 Self::new_none()
912 }
913 }
914 }
915
916 impl From<$index> for $optional_index {
917 fn from(index: $index) -> Self {
918 Self::new_some(index.0)
919 }
920 }
921
922 impl From<$optional_index> for Option<$index> {
923 fn from(optional_index: $optional_index) -> Self {
924 if optional_index.is_some() {
925 Some($index::new(optional_index.0))
926 } else {
927 None
928 }
929 }
930 }
931
932 impl From<usize> for $index {
937 fn from(value: usize) -> Self {
938 Self::new(
939 value
940 .try_into()
941 .ok()
942 .expect("index conversion from usize failed"),
943 )
944 }
945 }
946
947 impl From<usize> for $optional_index {
948 fn from(value: usize) -> Self {
949 Self::new_some(
950 value
951 .try_into()
952 .ok()
953 .expect("index conversion from usize failed"),
954 )
955 }
956 }
957
958 impl From<Option<usize>> for $optional_index {
959 fn from(value: Option<usize>) -> Self {
960 if let Some(value) = value {
961 Self::new_some(
962 value
963 .try_into()
964 .ok()
965 .expect("index conversion from usize failed"),
966 )
967 } else {
968 Self::new_none()
969 }
970 }
971 }
972
973 impl From<$index> for usize {
974 fn from(index: $index) -> Self {
975 index
976 .0
977 .try_into()
978 .ok()
979 .expect("index conversion to usize failed")
980 }
981 }
982
983 impl From<$optional_index> for Option<usize> {
984 fn from(index: $optional_index) -> Self {
985 if index.is_some() {
986 Some(
987 index
988 .0
989 .try_into()
990 .ok()
991 .expect("index conversion to usize failed"),
992 )
993 } else {
994 None
995 }
996 }
997 }
998
999 impl std::fmt::Debug for $index {
1004 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1005 write!(f, "{}({:?})", stringify!($index), self.0)
1006 }
1007 }
1008
1009 impl std::fmt::Debug for $optional_index {
1010 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1011 if self.is_some() {
1012 write!(f, "{}({:?})", stringify!($optional_index), self.0)
1013 } else {
1014 write!(f, "{}(None)", stringify!($optional_index))
1015 }
1016 }
1017 }
1018
1019 impl std::fmt::Display for $index {
1020 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1021 write!(f, "{}", self.0)
1022 }
1023 }
1024
1025 impl std::fmt::Display for $optional_index {
1026 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1027 if self.is_some() {
1028 write!(f, "{}", self.0)
1029 } else {
1030 write!(f, "None")
1031 }
1032 }
1033 }
1034
1035 impl Clone for $index {
1040 fn clone(&self) -> Self {
1041 *self
1042 }
1043 }
1044
1045 impl Clone for $optional_index {
1046 fn clone(&self) -> Self {
1047 *self
1048 }
1049 }
1050
1051 impl Copy for $index {}
1052
1053 impl Copy for $optional_index {}
1054
1055 impl PartialEq for $index {
1060 fn eq(&self, other: &Self) -> bool {
1061 self.0.eq(&other.0)
1062 }
1063 }
1064
1065 impl PartialEq for $optional_index {
1066 fn eq(&self, other: &Self) -> bool {
1067 self.0.eq(&other.0)
1068 }
1069 }
1070
1071 impl Eq for $index {}
1072
1073 impl Eq for $optional_index {}
1074
1075 impl PartialOrd for $index {
1080 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1081 Some(self.cmp(other))
1082 }
1083 }
1084
1085 impl PartialOrd for $optional_index {
1086 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1087 Some(self.cmp(other))
1088 }
1089 }
1090
1091 impl Ord for $index {
1092 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1093 self.0.cmp(&other.0)
1094 }
1095 }
1096
1097 impl Ord for $optional_index {
1098 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
1099 self.0.cmp(&other.0)
1100 }
1101 }
1102
1103 impl std::hash::Hash for $index {
1108 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1109 self.0.hash(state);
1110 }
1111 }
1112
1113 impl std::hash::Hash for $optional_index {
1114 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1115 self.0.hash(state);
1116 }
1117 }
1118 };
1119}