Skip to main content

optional_numeric_index/
lib.rs

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