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