1#[cfg(test)]
2mod tests;
3
4#[macro_export]
5macro_rules! implement_generic_index {
6 ($index:ident, $optional_index:ident) => {
7 #[repr(transparent)]
8 struct $index<IndexType>(IndexType);
9
10 #[repr(transparent)]
11 struct $optional_index<IndexType>(IndexType);
12
13 implement_generic_index!($index, $optional_index, __inner__);
14 };
15
16 (pub $index:ident, pub $optional_index:ident) => {
17 #[repr(transparent)]
18 pub struct $index<IndexType>(IndexType);
19
20 #[repr(transparent)]
21 pub struct $optional_index<IndexType>(IndexType);
22
23 implement_generic_index!($index, $optional_index, __inner__);
24 };
25
26 (pub(crate) $index:ident, pub(crate) $optional_index:ident) => {
27 #[repr(transparent)]
28 pub(crate) struct $index<IndexType>(IndexType);
29
30 #[repr(transparent)]
31 pub(crate) struct $optional_index<IndexType>(IndexType);
32
33 implement_generic_index!($index, $optional_index, __inner__);
34 };
35
36 (pub(super) $index:ident, pub(super) $optional_index:ident) => {
37 #[repr(transparent)]
38 pub(super) struct $index<IndexType>(IndexType);
39
40 #[repr(transparent)]
41 pub(super) struct $optional_index<IndexType>(IndexType);
42
43 implement_generic_index!($index, $optional_index, __inner__);
44 };
45
46 (pub(in $index_visibility:path) $index:ident, pub(in $optional_index_visibility:path) $optional_index:ident) => {
47 #[repr(transparent)]
48 pub(in $index_visibility) struct $index<IndexType>(IndexType);
49
50 #[repr(transparent)]
51 pub(in $optional_index_visibility) struct $optional_index<IndexType>(IndexType);
52
53 implement_generic_index!($index, $optional_index, __inner__);
54 };
55
56 ($index:ident, $optional_index:ident, __inner__) => {
57 impl<IndexType> $index<IndexType> {
62 #[allow(dead_code)]
63 pub fn new(value: IndexType) -> Self
64 where
65 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
66 {
67 assert_ne!(value, IndexType::max_value());
68 Self(value)
69 }
70
71 #[allow(dead_code)]
72 pub fn from_usize(value: usize) -> Self
73 where
74 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>,
75 {
76 Self::new(
77 value
78 .try_into()
79 .ok()
80 .expect("index conversion from usize failed"),
81 )
82 }
83
84 #[allow(dead_code)]
85 pub fn into_usize(self) -> usize
86 where
87 IndexType: TryInto<usize>,
88 {
89 self.0
90 .try_into()
91 .ok()
92 .expect("index conversion to usize failed")
93 }
94
95 #[allow(dead_code)]
96 pub fn from_raw(value: IndexType) -> Self
97 where
98 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
99 {
100 Self::new(value)
101 }
102
103 #[allow(dead_code)]
104 pub fn into_raw(self) -> IndexType {
105 self.0
106 }
107 }
108
109 impl<IndexType> $optional_index<IndexType> {
114 #[allow(dead_code)]
115 pub fn new_some(value: IndexType) -> Self
116 where
117 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
118 {
119 assert_ne!(value, IndexType::max_value());
120 Self(value)
121 }
122
123 #[allow(dead_code)]
124 pub fn new_none() -> Self
125 where
126 IndexType: num_traits::bounds::UpperBounded,
127 {
128 Self(IndexType::max_value())
129 }
130
131 #[allow(dead_code)]
132 pub fn from_option(option: Option<$index<IndexType>>) -> Self
133 where
134 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
135 {
136 Self::from(option)
137 }
138
139 #[allow(dead_code)]
140 pub fn into_option(self) -> Option<$index<IndexType>>
141 where
142 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
143 {
144 self.into()
145 }
146
147 #[allow(dead_code)]
148 pub fn expect(self, message: &str) -> $index<IndexType>
149 where
150 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
151 {
152 self.into_option().expect(message)
153 }
154
155 #[allow(dead_code)]
156 pub fn unwrap(self) -> $index<IndexType>
157 where
158 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
159 {
160 self.into_option().unwrap()
161 }
162
163 #[allow(dead_code)]
164 pub fn unwrap_or(self, default: $index<IndexType>) -> $index<IndexType>
165 where
166 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
167 {
168 self.into_option().unwrap_or(default)
169 }
170
171 #[allow(dead_code)]
172 pub fn unwrap_or_else(
173 self,
174 default: impl FnOnce() -> $index<IndexType>,
175 ) -> $index<IndexType>
176 where
177 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
178 {
179 self.into_option().unwrap_or_else(default)
180 }
181
182 #[allow(dead_code)]
183 pub unsafe fn unwrap_unchecked(self) -> $index<IndexType>
184 where
185 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
186 {
187 unsafe { self.into_option().unwrap_unchecked() }
188 }
189
190 #[allow(dead_code)]
191 pub fn from_usize(value: usize) -> Self
192 where
193 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>,
194 {
195 Self::new_some(
196 value
197 .try_into()
198 .ok()
199 .expect("index conversion from usize failed"),
200 )
201 }
202
203 #[allow(dead_code)]
204 pub fn from_option_usize(value: Option<usize>) -> Self
205 where
206 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>,
207 {
208 if let Some(value) = value {
209 Self::new_some(
210 value
211 .try_into()
212 .ok()
213 .expect("index conversion from usize failed"),
214 )
215 } else {
216 Self::new_none()
217 }
218 }
219
220 #[allow(dead_code)]
221 pub fn into_usize(self) -> Option<usize>
222 where
223 IndexType: num_traits::bounds::UpperBounded + Eq + TryInto<usize>,
224 {
225 if self.is_some() {
226 Some(
227 self.0
228 .try_into()
229 .ok()
230 .expect("index conversion to usize failed"),
231 )
232 } else {
233 None
234 }
235 }
236
237 #[allow(dead_code)]
238 pub fn from_raw(value: Option<IndexType>) -> Self
239 where
240 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
241 {
242 if let Some(value) = value {
243 Self::new_some(value)
244 } else {
245 Self::new_none()
246 }
247 }
248
249 #[allow(dead_code)]
250 pub fn into_raw(self) -> Option<IndexType>
251 where
252 IndexType: num_traits::bounds::UpperBounded + Eq,
253 {
254 if self.is_some() { Some(self.0) } else { None }
255 }
256
257 #[allow(dead_code)]
258 pub fn is_some(&self) -> bool
259 where
260 IndexType: num_traits::bounds::UpperBounded + Eq,
261 {
262 self.0 != IndexType::max_value()
263 }
264
265 #[allow(dead_code)]
266 pub fn is_none(&self) -> bool
267 where
268 IndexType: num_traits::bounds::UpperBounded + Eq,
269 {
270 self.0 == IndexType::max_value()
271 }
272
273 #[allow(dead_code)]
274 pub fn into_iter(self) -> impl Iterator<Item = $index<IndexType>>
275 where
276 IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug,
277 {
278 self.into_option().into_iter()
279 }
280 }
281
282 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug>
287 From<Option<$index<IndexType>>> for $optional_index<IndexType>
288 {
289 fn from(index: Option<$index<IndexType>>) -> Self {
290 if let Some(index) = index {
291 Self::new_some(index.0)
292 } else {
293 Self::new_none()
294 }
295 }
296 }
297
298 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug>
299 From<$index<IndexType>> for $optional_index<IndexType>
300 {
301 fn from(index: $index<IndexType>) -> Self {
302 Self::new_some(index.0)
303 }
304 }
305
306 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug>
307 From<$optional_index<IndexType>> for Option<$index<IndexType>>
308 {
309 fn from(optional_index: $optional_index<IndexType>) -> Self {
310 if optional_index.is_some() {
311 Some($index::new(optional_index.0))
312 } else {
313 None
314 }
315 }
316 }
317
318 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>>
323 From<usize> for $index<IndexType>
324 {
325 fn from(value: usize) -> Self {
326 Self::new(
327 value
328 .try_into()
329 .ok()
330 .expect("index conversion from usize failed"),
331 )
332 }
333 }
334
335 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>>
336 From<usize> for $optional_index<IndexType>
337 {
338 fn from(value: usize) -> Self {
339 Self::new_some(
340 value
341 .try_into()
342 .ok()
343 .expect("index conversion from usize failed"),
344 )
345 }
346 }
347
348 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryFrom<usize>>
349 From<Option<usize>> for $optional_index<IndexType>
350 {
351 fn from(value: Option<usize>) -> Self {
352 if let Some(value) = value {
353 Self::new_some(
354 value
355 .try_into()
356 .ok()
357 .expect("index conversion from usize failed"),
358 )
359 } else {
360 Self::new_none()
361 }
362 }
363 }
364
365 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug + TryInto<usize>>
366 From<$index<IndexType>> for usize
367 {
368 fn from(value: $index<IndexType>) -> Self {
369 value
370 .0
371 .try_into()
372 .ok()
373 .expect("index conversion from usize failed")
374 }
375 }
376
377 impl<IndexType: num_traits::bounds::UpperBounded + Eq + TryInto<usize>>
378 From<$optional_index<IndexType>> for Option<usize>
379 {
380 fn from(index: $optional_index<IndexType>) -> Self {
381 if index.is_some() {
382 Some(
383 index
384 .0
385 .try_into()
386 .ok()
387 .expect("index conversion to usize failed"),
388 )
389 } else {
390 None
391 }
392 }
393 }
394
395 impl<IndexType: std::fmt::Debug> std::fmt::Debug for $index<IndexType> {
400 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
401 write!(f, "{}({:?})", stringify!($index), self.0)
402 }
403 }
404
405 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Debug> std::fmt::Debug
406 for $optional_index<IndexType>
407 {
408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
409 if self.is_some() {
410 write!(f, "{}({:?})", stringify!($optional_index), self.0)
411 } else {
412 write!(f, "{}(None)", stringify!($optional_index))
413 }
414 }
415 }
416
417 impl<IndexType: std::fmt::Display> std::fmt::Display for $index<IndexType> {
418 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
419 write!(f, "{}", self.0)
420 }
421 }
422
423 impl<IndexType: num_traits::bounds::UpperBounded + Eq + std::fmt::Display> std::fmt::Display
424 for $optional_index<IndexType>
425 {
426 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
427 if self.is_some() {
428 write!(f, "{}", self.0)
429 } else {
430 write!(f, "None")
431 }
432 }
433 }
434
435 impl<IndexType: Clone> Clone for $index<IndexType> {
440 fn clone(&self) -> Self {
441 Self(self.0.clone())
442 }
443 }
444
445 impl<IndexType: Clone> Clone for $optional_index<IndexType> {
446 fn clone(&self) -> Self {
447 Self(self.0.clone())
448 }
449 }
450
451 impl<IndexType: Copy> Copy for $index<IndexType> {}
452
453 impl<IndexType: Copy> Copy for $optional_index<IndexType> {}
454
455 impl<IndexType: PartialEq> PartialEq for $index<IndexType> {
460 fn eq(&self, other: &Self) -> bool {
461 self.0.eq(&other.0)
462 }
463 }
464
465 impl<IndexType: PartialEq> PartialEq for $optional_index<IndexType> {
466 fn eq(&self, other: &Self) -> bool {
467 self.0.eq(&other.0)
468 }
469 }
470
471 impl<IndexType: Eq> Eq for $index<IndexType> {}
472
473 impl<IndexType: Eq> Eq for $optional_index<IndexType> {}
474
475 impl<IndexType: PartialOrd> PartialOrd for $index<IndexType> {
480 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
481 self.0.partial_cmp(&other.0)
482 }
483 }
484
485 impl<IndexType: PartialOrd> PartialOrd for $optional_index<IndexType> {
486 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
487 self.0.partial_cmp(&other.0)
488 }
489 }
490
491 impl<IndexType: Ord> Ord for $index<IndexType> {
492 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
493 self.0.cmp(&other.0)
494 }
495 }
496
497 impl<IndexType: Ord> Ord for $optional_index<IndexType> {
498 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
499 self.0.cmp(&other.0)
500 }
501 }
502
503 impl<IndexType: std::hash::Hash> std::hash::Hash for $index<IndexType> {
508 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
509 self.0.hash(state);
510 }
511 }
512
513 impl<IndexType: std::hash::Hash> std::hash::Hash for $optional_index<IndexType> {
514 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
515 self.0.hash(state);
516 }
517 }
518 };
519}
520
521#[macro_export]
522macro_rules! implement_fixed_index {
523 ($index:ident, $optional_index:ident, $index_type:ty) => {
524 #[repr(transparent)]
525 struct $index($index_type);
526
527 #[repr(transparent)]
528 struct $optional_index($index_type);
529
530 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
531 };
532
533 (pub $index:ident, pub $optional_index:ident, $index_type:ty) => {
534 pub struct $index($index_type);
535
536 pub struct $optional_index($index_type);
537
538 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
539 };
540
541 (pub(crate) $index:ident, pub(crate) $optional_index:ident, $index_type:ty) => {
542 pub(crate) struct $index($index_type);
543
544 pub(crate) struct $optional_index($index_type);
545
546 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
547 };
548
549 (pub(super) $index:ident, pub(super) $optional_index:ident, $index_type:ty) => {
550 pub(super) struct $index($index_type);
551
552 pub(super) struct $optional_index($index_type);
553
554 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
555 };
556
557 (pub(in $index_visibility:path) $index:ident, pub(in $optional_index_visibility:path) $optional_index:ident, $index_type:ty) => {
558 pub(in $index_visibility) struct $index($index_type);
559
560 pub(in $optional_index_visibility) struct $optional_index($index_type);
561
562 implement_fixed_index!($index, $optional_index, $index_type, __inner__);
563 };
564
565 ($index:ident, $optional_index:ident, $index_type:ty, __inner__) => {
566 impl $index {
571 #[allow(dead_code)]
572 pub fn new(value: $index_type) -> Self {
573 assert_ne!(value, num_traits::bounds::UpperBounded::max_value());
574 Self(value)
575 }
576
577 #[allow(dead_code)]
578 pub fn from_usize(value: usize) -> Self {
579 Self::new(
580 value
581 .try_into()
582 .ok()
583 .expect("index conversion from usize failed"),
584 )
585 }
586
587 #[allow(dead_code)]
588 pub fn into_usize(self) -> usize {
589 self.0
590 .try_into()
591 .ok()
592 .expect("index conversion to usize failed")
593 }
594
595 #[allow(dead_code)]
596 pub fn from_raw(value: $index_type) -> Self {
597 Self::new(value)
598 }
599
600 #[allow(dead_code)]
601 pub fn into_raw(self) -> $index_type {
602 self.0
603 }
604 }
605
606 impl $optional_index {
611 #[allow(dead_code)]
612 pub fn new_some(value: $index_type) -> Self {
613 assert_ne!(value, num_traits::bounds::UpperBounded::max_value());
614 Self(value)
615 }
616
617 #[allow(dead_code)]
618 pub fn new_none() -> Self {
619 Self(num_traits::bounds::UpperBounded::max_value())
620 }
621
622 #[allow(dead_code)]
623 pub fn from_option(option: Option<$index>) -> Self {
624 Self::from(option)
625 }
626
627 #[allow(dead_code)]
628 pub fn into_option(self) -> Option<$index> {
629 self.into()
630 }
631
632 #[allow(dead_code)]
633 pub fn expect(self, message: &str) -> $index {
634 self.into_option().expect(message)
635 }
636
637 #[allow(dead_code)]
638 pub fn unwrap(self) -> $index {
639 self.into_option().unwrap()
640 }
641
642 #[allow(dead_code)]
643 pub fn unwrap_or(self, default: $index) -> $index {
644 self.into_option().unwrap_or(default)
645 }
646
647 #[allow(dead_code)]
648 pub fn unwrap_or_else(self, default: impl FnOnce() -> $index) -> $index {
649 self.into_option().unwrap_or_else(default)
650 }
651
652 #[allow(dead_code)]
653 pub unsafe fn unwrap_unchecked(self) -> $index {
654 unsafe { self.into_option().unwrap_unchecked() }
655 }
656
657 #[allow(dead_code)]
658 pub fn from_usize(value: usize) -> Self {
659 Self::new_some(
660 value
661 .try_into()
662 .ok()
663 .expect("index conversion from usize failed"),
664 )
665 }
666
667 #[allow(dead_code)]
668 pub fn from_option_usize(value: Option<usize>) -> Self {
669 if let Some(value) = value {
670 Self::new_some(
671 value
672 .try_into()
673 .ok()
674 .expect("index conversion from usize failed"),
675 )
676 } else {
677 Self::new_none()
678 }
679 }
680
681 #[allow(dead_code)]
682 pub fn into_usize(self) -> Option<usize> {
683 if self.is_some() {
684 Some(
685 self.0
686 .try_into()
687 .ok()
688 .expect("index conversion to usize failed"),
689 )
690 } else {
691 None
692 }
693 }
694
695 #[allow(dead_code)]
696 pub fn from_raw(value: Option<$index_type>) -> Self {
697 if let Some(value) = value {
698 Self::new_some(value)
699 } else {
700 Self::new_none()
701 }
702 }
703
704 #[allow(dead_code)]
705 pub fn into_raw(self) -> Option<$index_type> {
706 if self.is_some() { Some(self.0) } else { None }
707 }
708
709 #[allow(dead_code)]
710 pub fn is_some(&self) -> bool {
711 self.0 != num_traits::bounds::UpperBounded::max_value()
712 }
713
714 #[allow(dead_code)]
715 pub fn is_none(&self) -> bool {
716 self.0 == num_traits::bounds::UpperBounded::max_value()
717 }
718
719 #[allow(dead_code)]
720 pub fn into_iter(self) -> impl Iterator<Item = $index> {
721 self.into_option().into_iter()
722 }
723 }
724
725 impl From<Option<$index>> for $optional_index {
730 fn from(index: Option<$index>) -> Self {
731 if let Some(index) = index {
732 Self::new_some(index.0)
733 } else {
734 Self::new_none()
735 }
736 }
737 }
738
739 impl From<$index> for $optional_index {
740 fn from(index: $index) -> Self {
741 Self::new_some(index.0)
742 }
743 }
744
745 impl From<$optional_index> for Option<$index> {
746 fn from(optional_index: $optional_index) -> Self {
747 if optional_index.is_some() {
748 Some($index::new(optional_index.0))
749 } else {
750 None
751 }
752 }
753 }
754
755 impl From<usize> for $index {
760 fn from(value: usize) -> Self {
761 Self::new(
762 value
763 .try_into()
764 .ok()
765 .expect("index conversion from usize failed"),
766 )
767 }
768 }
769
770 impl From<usize> for $optional_index {
771 fn from(value: usize) -> Self {
772 Self::new_some(
773 value
774 .try_into()
775 .ok()
776 .expect("index conversion from usize failed"),
777 )
778 }
779 }
780
781 impl From<Option<usize>> for $optional_index {
782 fn from(value: Option<usize>) -> Self {
783 if let Some(value) = value {
784 Self::new_some(
785 value
786 .try_into()
787 .ok()
788 .expect("index conversion from usize failed"),
789 )
790 } else {
791 Self::new_none()
792 }
793 }
794 }
795
796 impl From<$index> for usize {
797 fn from(index: $index) -> Self {
798 index
799 .0
800 .try_into()
801 .ok()
802 .expect("index conversion to usize failed")
803 }
804 }
805
806 impl From<$optional_index> for Option<usize> {
807 fn from(index: $optional_index) -> Self {
808 if index.is_some() {
809 Some(
810 index
811 .0
812 .try_into()
813 .ok()
814 .expect("index conversion to usize failed"),
815 )
816 } else {
817 None
818 }
819 }
820 }
821
822 impl std::fmt::Debug for $index {
827 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
828 write!(f, "{}({:?})", stringify!($index), self.0)
829 }
830 }
831
832 impl std::fmt::Debug for $optional_index {
833 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834 if self.is_some() {
835 write!(f, "{}({:?})", stringify!($optional_index), self.0)
836 } else {
837 write!(f, "{}(None)", stringify!($optional_index))
838 }
839 }
840 }
841
842 impl std::fmt::Display for $index {
843 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
844 write!(f, "{}", self.0)
845 }
846 }
847
848 impl std::fmt::Display for $optional_index {
849 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
850 if self.is_some() {
851 write!(f, "{}", self.0)
852 } else {
853 write!(f, "None")
854 }
855 }
856 }
857
858 impl Clone for $index {
863 fn clone(&self) -> Self {
864 *self
865 }
866 }
867
868 impl Clone for $optional_index {
869 fn clone(&self) -> Self {
870 *self
871 }
872 }
873
874 impl Copy for $index {}
875
876 impl Copy for $optional_index {}
877
878 impl PartialEq for $index {
883 fn eq(&self, other: &Self) -> bool {
884 self.0.eq(&other.0)
885 }
886 }
887
888 impl PartialEq for $optional_index {
889 fn eq(&self, other: &Self) -> bool {
890 self.0.eq(&other.0)
891 }
892 }
893
894 impl Eq for $index {}
895
896 impl Eq for $optional_index {}
897
898 impl PartialOrd for $index {
903 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
904 Some(self.cmp(other))
905 }
906 }
907
908 impl PartialOrd for $optional_index {
909 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
910 Some(self.cmp(other))
911 }
912 }
913
914 impl Ord for $index {
915 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
916 self.0.cmp(&other.0)
917 }
918 }
919
920 impl Ord for $optional_index {
921 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
922 self.0.cmp(&other.0)
923 }
924 }
925
926 impl std::hash::Hash for $index {
931 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
932 self.0.hash(state);
933 }
934 }
935
936 impl std::hash::Hash for $optional_index {
937 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
938 self.0.hash(state);
939 }
940 }
941 };
942}