1use core::mem::size_of;
2use core::num::Wrapping;
3use core::num::{
4 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
5 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
6};
7
8c0nst::c0nst! {
9pub c0nst trait ToPrimitive {
20 fn to_isize(&self) -> Option<isize> {
23 match self.to_i64() { Some(v) => crate::CheckedCast::<isize>::checked_cast(v), None => None }
24 }
25
26 fn to_i8(&self) -> Option<i8> {
29 match self.to_i64() { Some(v) => crate::CheckedCast::<i8>::checked_cast(v), None => None }
30 }
31
32 fn to_i16(&self) -> Option<i16> {
35 match self.to_i64() { Some(v) => crate::CheckedCast::<i16>::checked_cast(v), None => None }
36 }
37
38 fn to_i32(&self) -> Option<i32> {
41 match self.to_i64() { Some(v) => crate::CheckedCast::<i32>::checked_cast(v), None => None }
42 }
43
44 fn to_i64(&self) -> Option<i64>;
47
48 fn to_i128(&self) -> Option<i128> {
51 match self.to_i64() {
54 Some(i) => Some(i as i128),
55 None => match self.to_u64() {
56 Some(u) => Some(u as i128),
57 None => None,
58 },
59 }
60 }
61
62 fn to_usize(&self) -> Option<usize> {
65 match self.to_u64() { Some(v) => crate::CheckedCast::<usize>::checked_cast(v), None => None }
66 }
67
68 fn to_u8(&self) -> Option<u8> {
71 match self.to_u64() { Some(v) => crate::CheckedCast::<u8>::checked_cast(v), None => None }
72 }
73
74 fn to_u16(&self) -> Option<u16> {
77 match self.to_u64() { Some(v) => crate::CheckedCast::<u16>::checked_cast(v), None => None }
78 }
79
80 fn to_u32(&self) -> Option<u32> {
83 match self.to_u64() { Some(v) => crate::CheckedCast::<u32>::checked_cast(v), None => None }
84 }
85
86 fn to_u64(&self) -> Option<u64>;
89
90 fn to_u128(&self) -> Option<u128> {
93 match self.to_u64() { Some(u) => Some(u as u128), None => None }
94 }
95
96 fn to_f32(&self) -> Option<f32> {
100 match self.to_f64() {
104 Some(v) => Some(v as f32),
105 None => None,
106 }
107 }
108
109 fn to_f64(&self) -> Option<f64> {
113 match self.to_i64() {
114 Some(i) => Some(i as f64),
115 None => match self.to_u64() { Some(u) => Some(u as f64), None => None },
116 }
117 }
118}
119}
120
121macro_rules! impl_to_primitive_int_to_int {
122 ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
123 #[inline]
124 fn $method(&self) -> Option<$DstT> {
125 let min = $DstT::MIN as $SrcT;
126 let max = $DstT::MAX as $SrcT;
127 if size_of::<$SrcT>() <= size_of::<$DstT>() || (min <= *self && *self <= max) {
128 Some(*self as $DstT)
129 } else {
130 None
131 }
132 }
133 )*}
134}
135
136macro_rules! impl_to_primitive_int_to_uint {
137 ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
138 #[inline]
139 fn $method(&self) -> Option<$DstT> {
140 let max = $DstT::MAX as $SrcT;
141 if 0 <= *self && (size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max) {
142 Some(*self as $DstT)
143 } else {
144 None
145 }
146 }
147 )*}
148}
149
150macro_rules! impl_to_primitive_int {
151 ($T:ident) => {
152 c0nst::c0nst! {
153 c0nst impl ToPrimitive for $T {
154 impl_to_primitive_int_to_int! { $T:
155 fn to_isize -> isize;
156 fn to_i8 -> i8;
157 fn to_i16 -> i16;
158 fn to_i32 -> i32;
159 fn to_i64 -> i64;
160 fn to_i128 -> i128;
161 }
162
163 impl_to_primitive_int_to_uint! { $T:
164 fn to_usize -> usize;
165 fn to_u8 -> u8;
166 fn to_u16 -> u16;
167 fn to_u32 -> u32;
168 fn to_u64 -> u64;
169 fn to_u128 -> u128;
170 }
171
172 #[inline]
173 fn to_f32(&self) -> Option<f32> {
174 Some(*self as f32)
175 }
176 #[inline]
177 fn to_f64(&self) -> Option<f64> {
178 Some(*self as f64)
179 }
180 }
181 }
182 };
183}
184
185impl_to_primitive_int!(isize);
186impl_to_primitive_int!(i8);
187impl_to_primitive_int!(i16);
188impl_to_primitive_int!(i32);
189impl_to_primitive_int!(i64);
190impl_to_primitive_int!(i128);
191
192macro_rules! impl_to_primitive_uint_to_int {
193 ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
194 #[inline]
195 fn $method(&self) -> Option<$DstT> {
196 let max = $DstT::MAX as $SrcT;
197 if size_of::<$SrcT>() < size_of::<$DstT>() || *self <= max {
198 Some(*self as $DstT)
199 } else {
200 None
201 }
202 }
203 )*}
204}
205
206macro_rules! impl_to_primitive_uint_to_uint {
207 ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
208 #[inline]
209 fn $method(&self) -> Option<$DstT> {
210 let max = $DstT::MAX as $SrcT;
211 if size_of::<$SrcT>() <= size_of::<$DstT>() || *self <= max {
212 Some(*self as $DstT)
213 } else {
214 None
215 }
216 }
217 )*}
218}
219
220macro_rules! impl_to_primitive_uint {
221 ($T:ident) => {
222 c0nst::c0nst! {
223 c0nst impl ToPrimitive for $T {
224 impl_to_primitive_uint_to_int! { $T:
225 fn to_isize -> isize;
226 fn to_i8 -> i8;
227 fn to_i16 -> i16;
228 fn to_i32 -> i32;
229 fn to_i64 -> i64;
230 fn to_i128 -> i128;
231 }
232
233 impl_to_primitive_uint_to_uint! { $T:
234 fn to_usize -> usize;
235 fn to_u8 -> u8;
236 fn to_u16 -> u16;
237 fn to_u32 -> u32;
238 fn to_u64 -> u64;
239 fn to_u128 -> u128;
240 }
241
242 #[inline]
243 fn to_f32(&self) -> Option<f32> {
244 Some(*self as f32)
245 }
246 #[inline]
247 fn to_f64(&self) -> Option<f64> {
248 Some(*self as f64)
249 }
250 }
251 }
252 };
253}
254
255impl_to_primitive_uint!(usize);
256impl_to_primitive_uint!(u8);
257impl_to_primitive_uint!(u16);
258impl_to_primitive_uint!(u32);
259impl_to_primitive_uint!(u64);
260impl_to_primitive_uint!(u128);
261
262macro_rules! impl_to_primitive_nonzero_to_method {
263 ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
264 #[inline]
265 fn $method(&self) -> Option<$DstT> {
266 self.get().$method()
267 }
268 )*}
269}
270
271macro_rules! impl_to_primitive_nonzero {
272 ($T:ident) => {
273 c0nst::c0nst! {
274 c0nst impl ToPrimitive for $T {
275 impl_to_primitive_nonzero_to_method! { $T:
276 fn to_isize -> isize;
277 fn to_i8 -> i8;
278 fn to_i16 -> i16;
279 fn to_i32 -> i32;
280 fn to_i64 -> i64;
281 fn to_i128 -> i128;
282
283 fn to_usize -> usize;
284 fn to_u8 -> u8;
285 fn to_u16 -> u16;
286 fn to_u32 -> u32;
287 fn to_u64 -> u64;
288 fn to_u128 -> u128;
289
290 fn to_f32 -> f32;
291 fn to_f64 -> f64;
292 }
293 }
294 }
295 };
296}
297
298impl_to_primitive_nonzero!(NonZeroUsize);
299impl_to_primitive_nonzero!(NonZeroU8);
300impl_to_primitive_nonzero!(NonZeroU16);
301impl_to_primitive_nonzero!(NonZeroU32);
302impl_to_primitive_nonzero!(NonZeroU64);
303impl_to_primitive_nonzero!(NonZeroU128);
304
305impl_to_primitive_nonzero!(NonZeroIsize);
306impl_to_primitive_nonzero!(NonZeroI8);
307impl_to_primitive_nonzero!(NonZeroI16);
308impl_to_primitive_nonzero!(NonZeroI32);
309impl_to_primitive_nonzero!(NonZeroI64);
310impl_to_primitive_nonzero!(NonZeroI128);
311
312macro_rules! impl_to_primitive_float_to_float {
313 ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
314 #[inline]
315 fn $method(&self) -> Option<$DstT> {
316 Some(*self as $DstT)
319 }
320 )*}
321}
322
323macro_rules! float_to_int_unchecked {
324 ($float:expr => $int:ty) => {
328 $float as $int
329 };
330}
331
332macro_rules! impl_to_primitive_float_to_signed_int {
333 ($f:ident : $( fn $method:ident -> $i:ident ; )*) => {$(
334 #[inline]
335 fn $method(&self) -> Option<$i> {
336 if size_of::<$f>() > size_of::<$i>() {
339 const MIN_M1: $f = $i::MIN as $f - 1.0;
341 const MAX_P1: $f = $i::MAX as $f + 1.0;
342 if *self > MIN_M1 && *self < MAX_P1 {
343 return Some(float_to_int_unchecked!(*self => $i));
344 }
345 } else {
346 const MIN: $f = $i::MIN as $f;
349 const MAX_P1: $f = $i::MAX as $f;
352 if *self >= MIN && *self < MAX_P1 {
353 return Some(float_to_int_unchecked!(*self => $i));
354 }
355 }
356 None
357 }
358 )*}
359}
360
361macro_rules! impl_to_primitive_float_to_unsigned_int {
362 ($f:ident : $( fn $method:ident -> $u:ident ; )*) => {$(
363 #[inline]
364 fn $method(&self) -> Option<$u> {
365 if size_of::<$f>() > size_of::<$u>() {
368 const MAX_P1: $f = $u::MAX as $f + 1.0;
370 if *self > -1.0 && *self < MAX_P1 {
371 return Some(float_to_int_unchecked!(*self => $u));
372 }
373 } else {
374 const MAX_P1: $f = $u::MAX as $f;
378 if *self > -1.0 && *self < MAX_P1 {
379 return Some(float_to_int_unchecked!(*self => $u));
380 }
381 }
382 None
383 }
384 )*}
385}
386
387macro_rules! impl_to_primitive_float {
388 ($T:ident) => {
389 c0nst::c0nst! {
390 c0nst impl ToPrimitive for $T {
391 impl_to_primitive_float_to_signed_int! { $T:
392 fn to_isize -> isize;
393 fn to_i8 -> i8;
394 fn to_i16 -> i16;
395 fn to_i32 -> i32;
396 fn to_i64 -> i64;
397 fn to_i128 -> i128;
398 }
399
400 impl_to_primitive_float_to_unsigned_int! { $T:
401 fn to_usize -> usize;
402 fn to_u8 -> u8;
403 fn to_u16 -> u16;
404 fn to_u32 -> u32;
405 fn to_u64 -> u64;
406 fn to_u128 -> u128;
407 }
408
409 impl_to_primitive_float_to_float! { $T:
410 fn to_f32 -> f32;
411 fn to_f64 -> f64;
412 }
413 }
414 }
415 };
416}
417
418impl_to_primitive_float!(f32);
419impl_to_primitive_float!(f64);
420
421c0nst::c0nst! {
422pub c0nst trait FromPrimitive: Sized {
433 fn from_isize(n: isize) -> Option<Self> { Self::from_i64(n as i64) }
436
437 fn from_i8(n: i8) -> Option<Self> { Self::from_i64(n as i64) }
440
441 fn from_i16(n: i16) -> Option<Self> { Self::from_i64(n as i64) }
444
445 fn from_i32(n: i32) -> Option<Self> { Self::from_i64(n as i64) }
448
449 fn from_i64(n: i64) -> Option<Self>;
452
453 fn from_i128(n: i128) -> Option<Self> {
456 if n >= 0 {
460 Self::from_u128(n as u128)
461 } else if n >= i64::MIN as i128 {
462 Self::from_i64(n as i64)
463 } else {
464 None
465 }
466 }
467
468 fn from_usize(n: usize) -> Option<Self> { Self::from_u64(n as u64) }
471
472 fn from_u8(n: u8) -> Option<Self> { Self::from_u64(n as u64) }
475
476 fn from_u16(n: u16) -> Option<Self> { Self::from_u64(n as u64) }
479
480 fn from_u32(n: u32) -> Option<Self> { Self::from_u64(n as u64) }
483
484 fn from_u64(n: u64) -> Option<Self>;
487
488 fn from_u128(n: u128) -> Option<Self> {
491 if n <= u64::MAX as u128 { Self::from_u64(n as u64) } else { None }
492 }
493
494 fn from_f32(n: f32) -> Option<Self> { Self::from_f64(n as f64) }
497
498 fn from_f64(n: f64) -> Option<Self> {
501 match crate::ToPrimitive::to_i64(&n) {
502 Some(i) => Self::from_i64(i),
503 None => match crate::ToPrimitive::to_u64(&n) { Some(u) => Self::from_u64(u), None => None },
504 }
505 }
506}
507}
508
509macro_rules! impl_from_primitive {
510 ($T:ty, $to_ty:ident) => {
511 c0nst::c0nst! {
512 c0nst impl FromPrimitive for $T {
513 #[inline]
514 fn from_isize(n: isize) -> Option<$T> {
515 n.$to_ty()
516 }
517 #[inline]
518 fn from_i8(n: i8) -> Option<$T> {
519 n.$to_ty()
520 }
521 #[inline]
522 fn from_i16(n: i16) -> Option<$T> {
523 n.$to_ty()
524 }
525 #[inline]
526 fn from_i32(n: i32) -> Option<$T> {
527 n.$to_ty()
528 }
529 #[inline]
530 fn from_i64(n: i64) -> Option<$T> {
531 n.$to_ty()
532 }
533 #[inline]
534 fn from_i128(n: i128) -> Option<$T> {
535 n.$to_ty()
536 }
537
538 #[inline]
539 fn from_usize(n: usize) -> Option<$T> {
540 n.$to_ty()
541 }
542 #[inline]
543 fn from_u8(n: u8) -> Option<$T> {
544 n.$to_ty()
545 }
546 #[inline]
547 fn from_u16(n: u16) -> Option<$T> {
548 n.$to_ty()
549 }
550 #[inline]
551 fn from_u32(n: u32) -> Option<$T> {
552 n.$to_ty()
553 }
554 #[inline]
555 fn from_u64(n: u64) -> Option<$T> {
556 n.$to_ty()
557 }
558 #[inline]
559 fn from_u128(n: u128) -> Option<$T> {
560 n.$to_ty()
561 }
562
563 #[inline]
564 fn from_f32(n: f32) -> Option<$T> {
565 n.$to_ty()
566 }
567 #[inline]
568 fn from_f64(n: f64) -> Option<$T> {
569 n.$to_ty()
570 }
571 }
572 }
573 };
574}
575
576impl_from_primitive!(isize, to_isize);
577impl_from_primitive!(i8, to_i8);
578impl_from_primitive!(i16, to_i16);
579impl_from_primitive!(i32, to_i32);
580impl_from_primitive!(i64, to_i64);
581impl_from_primitive!(i128, to_i128);
582impl_from_primitive!(usize, to_usize);
583impl_from_primitive!(u8, to_u8);
584impl_from_primitive!(u16, to_u16);
585impl_from_primitive!(u32, to_u32);
586impl_from_primitive!(u64, to_u64);
587impl_from_primitive!(u128, to_u128);
588impl_from_primitive!(f32, to_f32);
589impl_from_primitive!(f64, to_f64);
590
591macro_rules! impl_from_primitive_nonzero_one {
594 ($t:ty, $T:ty, $to_ty:ident, $method:ident) => {
595 #[inline]
596 fn $method(n: $t) -> Option<$T> {
597 match n.$to_ty() {
598 Some(v) => Self::new(v),
599 None => None,
600 }
601 }
602 };
603}
604
605macro_rules! impl_from_primitive_nonzero {
606 ($T:ty, $to_ty:ident) => {
607 c0nst::c0nst! {
608 c0nst impl FromPrimitive for $T {
609 impl_from_primitive_nonzero_one!(isize, $T, $to_ty, from_isize);
610 impl_from_primitive_nonzero_one!(i8, $T, $to_ty, from_i8);
611 impl_from_primitive_nonzero_one!(i16, $T, $to_ty, from_i16);
612 impl_from_primitive_nonzero_one!(i32, $T, $to_ty, from_i32);
613 impl_from_primitive_nonzero_one!(i64, $T, $to_ty, from_i64);
614 impl_from_primitive_nonzero_one!(i128, $T, $to_ty, from_i128);
615
616 impl_from_primitive_nonzero_one!(usize, $T, $to_ty, from_usize);
617 impl_from_primitive_nonzero_one!(u8, $T, $to_ty, from_u8);
618 impl_from_primitive_nonzero_one!(u16, $T, $to_ty, from_u16);
619 impl_from_primitive_nonzero_one!(u32, $T, $to_ty, from_u32);
620 impl_from_primitive_nonzero_one!(u64, $T, $to_ty, from_u64);
621 impl_from_primitive_nonzero_one!(u128, $T, $to_ty, from_u128);
622
623 impl_from_primitive_nonzero_one!(f32, $T, $to_ty, from_f32);
624 impl_from_primitive_nonzero_one!(f64, $T, $to_ty, from_f64);
625 }
626 }
627 };
628}
629
630impl_from_primitive_nonzero!(NonZeroIsize, to_isize);
631impl_from_primitive_nonzero!(NonZeroI8, to_i8);
632impl_from_primitive_nonzero!(NonZeroI16, to_i16);
633impl_from_primitive_nonzero!(NonZeroI32, to_i32);
634impl_from_primitive_nonzero!(NonZeroI64, to_i64);
635impl_from_primitive_nonzero!(NonZeroI128, to_i128);
636impl_from_primitive_nonzero!(NonZeroUsize, to_usize);
637impl_from_primitive_nonzero!(NonZeroU8, to_u8);
638impl_from_primitive_nonzero!(NonZeroU16, to_u16);
639impl_from_primitive_nonzero!(NonZeroU32, to_u32);
640impl_from_primitive_nonzero!(NonZeroU64, to_u64);
641impl_from_primitive_nonzero!(NonZeroU128, to_u128);
642
643macro_rules! impl_to_primitive_wrapping {
644 ($( fn $method:ident -> $i:ident ; )*) => {$(
645 #[inline]
646 fn $method(&self) -> Option<$i> {
647 (self.0).$method()
648 }
649 )*}
650}
651
652c0nst::c0nst! {
653c0nst impl<T: [c0nst] ToPrimitive> ToPrimitive for Wrapping<T> {
654 impl_to_primitive_wrapping! {
655 fn to_isize -> isize;
656 fn to_i8 -> i8;
657 fn to_i16 -> i16;
658 fn to_i32 -> i32;
659 fn to_i64 -> i64;
660 fn to_i128 -> i128;
661
662 fn to_usize -> usize;
663 fn to_u8 -> u8;
664 fn to_u16 -> u16;
665 fn to_u32 -> u32;
666 fn to_u64 -> u64;
667 fn to_u128 -> u128;
668
669 fn to_f32 -> f32;
670 fn to_f64 -> f64;
671 }
672}
673}
674
675macro_rules! impl_from_primitive_wrapping {
676 ($( fn $method:ident ( $i:ident ); )*) => {$(
677 #[inline]
678 fn $method(n: $i) -> Option<Self> {
679 match T::$method(n) {
681 Some(v) => Some(Wrapping(v)),
682 None => None,
683 }
684 }
685 )*}
686}
687
688c0nst::c0nst! {
689c0nst impl<T: [c0nst] FromPrimitive + [c0nst] Destruct> FromPrimitive for Wrapping<T> {
690 impl_from_primitive_wrapping! {
691 fn from_isize(isize);
692 fn from_i8(i8);
693 fn from_i16(i16);
694 fn from_i32(i32);
695 fn from_i64(i64);
696 fn from_i128(i128);
697
698 fn from_usize(usize);
699 fn from_u8(u8);
700 fn from_u16(u16);
701 fn from_u32(u32);
702 fn from_u64(u64);
703 fn from_u128(u128);
704
705 fn from_f32(f32);
706 fn from_f64(f64);
707 }
708}
709}
710
711c0nst::c0nst! {
712#[inline]
723pub c0nst fn cast<T: [c0nst] NumCast + [c0nst] Destruct, U: [c0nst] NumCast>(n: T) -> Option<U> {
724 NumCast::from(n)
725}
726}
727
728c0nst::c0nst! {
729pub c0nst trait NumCast: Sized + [c0nst] ToPrimitive {
731 fn from<T: [c0nst] ToPrimitive + [c0nst] Destruct>(n: T) -> Option<Self>;
744}
745}
746
747macro_rules! impl_num_cast {
748 ($T:ty, $conv:ident) => {
749 c0nst::c0nst! {
750 c0nst impl NumCast for $T {
751 #[inline]
752 fn from<N: [c0nst] ToPrimitive + [c0nst] Destruct>(n: N) -> Option<$T> {
753 n.$conv()
754 }
755 }
756 }
757 };
758}
759
760impl_num_cast!(u8, to_u8);
761impl_num_cast!(u16, to_u16);
762impl_num_cast!(u32, to_u32);
763impl_num_cast!(u64, to_u64);
764impl_num_cast!(u128, to_u128);
765impl_num_cast!(usize, to_usize);
766impl_num_cast!(i8, to_i8);
767impl_num_cast!(i16, to_i16);
768impl_num_cast!(i32, to_i32);
769impl_num_cast!(i64, to_i64);
770impl_num_cast!(i128, to_i128);
771impl_num_cast!(isize, to_isize);
772impl_num_cast!(f32, to_f32);
773impl_num_cast!(f64, to_f64);
774
775macro_rules! impl_num_cast_nonzero {
776 ($T:ty, $conv:ident) => {
777 c0nst::c0nst! {
778 c0nst impl NumCast for $T {
779 #[inline]
780 fn from<N: [c0nst] ToPrimitive + [c0nst] Destruct>(n: N) -> Option<$T> {
781 match n.$conv() {
783 Some(v) => Self::new(v),
784 None => None,
785 }
786 }
787 }
788 }
789 };
790}
791
792impl_num_cast_nonzero!(NonZeroUsize, to_usize);
793impl_num_cast_nonzero!(NonZeroU8, to_u8);
794impl_num_cast_nonzero!(NonZeroU16, to_u16);
795impl_num_cast_nonzero!(NonZeroU32, to_u32);
796impl_num_cast_nonzero!(NonZeroU64, to_u64);
797impl_num_cast_nonzero!(NonZeroU128, to_u128);
798
799impl_num_cast_nonzero!(NonZeroIsize, to_isize);
800impl_num_cast_nonzero!(NonZeroI8, to_i8);
801impl_num_cast_nonzero!(NonZeroI16, to_i16);
802impl_num_cast_nonzero!(NonZeroI32, to_i32);
803impl_num_cast_nonzero!(NonZeroI64, to_i64);
804impl_num_cast_nonzero!(NonZeroI128, to_i128);
805
806c0nst::c0nst! {
807c0nst impl<T: [c0nst] NumCast + [c0nst] Destruct> NumCast for Wrapping<T> {
808 fn from<U: [c0nst] ToPrimitive + [c0nst] Destruct>(n: U) -> Option<Self> {
809 match T::from(n) {
811 Some(v) => Some(Wrapping(v)),
812 None => None,
813 }
814 }
815}
816}
817
818c0nst::c0nst! {
819pub c0nst trait AsPrimitive<T>: 'static + Copy
846where
847 T: 'static + Copy,
848{
849 fn as_(self) -> T;
851}
852}
853
854macro_rules! impl_as_primitive {
855 (@ $T: ty => impl $U: ty ) => {
856 c0nst::c0nst! {
857 c0nst impl AsPrimitive<$U> for $T {
858 #[inline] fn as_(self) -> $U { self as $U }
859 }
860 }
861 };
862 (@ $T: ty => { $( $U: ty ),* } ) => {$(
863 impl_as_primitive!(@ $T => impl $U);
864 )*};
865 ($T: ty => { $( $U: ty ),* } ) => {
866 impl_as_primitive!(@ $T => { $( $U ),* });
867 impl_as_primitive!(@ $T => { u8, u16, u32, u64, u128, usize });
868 impl_as_primitive!(@ $T => { i8, i16, i32, i64, i128, isize });
869 };
870}
871
872impl_as_primitive!(u8 => { char, f32, f64 });
873impl_as_primitive!(i8 => { f32, f64 });
874impl_as_primitive!(u16 => { f32, f64 });
875impl_as_primitive!(i16 => { f32, f64 });
876impl_as_primitive!(u32 => { f32, f64 });
877impl_as_primitive!(i32 => { f32, f64 });
878impl_as_primitive!(u64 => { f32, f64 });
879impl_as_primitive!(i64 => { f32, f64 });
880impl_as_primitive!(u128 => { f32, f64 });
881impl_as_primitive!(i128 => { f32, f64 });
882impl_as_primitive!(usize => { f32, f64 });
883impl_as_primitive!(isize => { f32, f64 });
884impl_as_primitive!(f32 => { f32, f64 });
885impl_as_primitive!(f64 => { f32, f64 });
886impl_as_primitive!(char => { char });
887impl_as_primitive!(bool => {});
888
889#[macro_export]
920macro_rules! impl_to_primitive_minimal {
921 (impl ToPrimitive for $t:ty {
922 to_i64 = $to_i64:expr,
923 to_u64 = $to_u64:expr $(,)?
924 }) => {
925 impl $crate::ToPrimitive for $t {
926 #[inline]
927 fn to_i64(&self) -> Option<i64> {
928 ($to_i64)(self)
929 }
930
931 #[inline]
932 fn to_u64(&self) -> Option<u64> {
933 ($to_u64)(self)
934 }
935
936 #[inline]
937 fn to_isize(&self) -> Option<isize> {
938 self.to_i64()
939 .and_then(|v| $crate::CheckedCast::<isize>::checked_cast(v))
940 }
941
942 #[inline]
943 fn to_i8(&self) -> Option<i8> {
944 self.to_i64()
945 .and_then(|v| $crate::CheckedCast::<i8>::checked_cast(v))
946 }
947
948 #[inline]
949 fn to_i16(&self) -> Option<i16> {
950 self.to_i64()
951 .and_then(|v| $crate::CheckedCast::<i16>::checked_cast(v))
952 }
953
954 #[inline]
955 fn to_i32(&self) -> Option<i32> {
956 self.to_i64()
957 .and_then(|v| $crate::CheckedCast::<i32>::checked_cast(v))
958 }
959
960 #[inline]
961 fn to_i128(&self) -> Option<i128> {
962 match self.to_i64() {
963 Some(i) => Some(i128::from(i)),
964 None => self.to_u64().map(i128::from),
965 }
966 }
967
968 #[inline]
969 fn to_usize(&self) -> Option<usize> {
970 self.to_u64()
971 .and_then(|v| $crate::CheckedCast::<usize>::checked_cast(v))
972 }
973
974 #[inline]
975 fn to_u8(&self) -> Option<u8> {
976 self.to_u64()
977 .and_then(|v| $crate::CheckedCast::<u8>::checked_cast(v))
978 }
979
980 #[inline]
981 fn to_u16(&self) -> Option<u16> {
982 self.to_u64()
983 .and_then(|v| $crate::CheckedCast::<u16>::checked_cast(v))
984 }
985
986 #[inline]
987 fn to_u32(&self) -> Option<u32> {
988 self.to_u64()
989 .and_then(|v| $crate::CheckedCast::<u32>::checked_cast(v))
990 }
991
992 #[inline]
993 fn to_u128(&self) -> Option<u128> {
994 self.to_u64().map(u128::from)
995 }
996
997 #[inline]
998 fn to_f32(&self) -> Option<f32> {
999 self.to_f64().map(|v| v as f32)
1002 }
1003
1004 #[inline]
1005 fn to_f64(&self) -> Option<f64> {
1006 match self.to_i64() {
1007 Some(i) => Some(i as f64),
1008 None => self.to_u64().map(|u| u as f64),
1009 }
1010 }
1011 }
1012 };
1013}
1014
1015#[macro_export]
1041macro_rules! impl_from_primitive_minimal {
1042 (impl FromPrimitive for $t:ty {
1043 from_i64 = $from_i64:expr,
1044 from_u64 = $from_u64:expr $(,)?
1045 }) => {
1046 impl $crate::FromPrimitive for $t {
1047 #[inline]
1048 fn from_i64(n: i64) -> Option<Self> {
1049 ($from_i64)(n)
1050 }
1051
1052 #[inline]
1053 fn from_u64(n: u64) -> Option<Self> {
1054 ($from_u64)(n)
1055 }
1056
1057 #[inline]
1058 fn from_isize(n: isize) -> Option<Self> {
1059 Self::from_i64(n as i64)
1060 }
1061
1062 #[inline]
1063 fn from_i8(n: i8) -> Option<Self> {
1064 Self::from_i64(i64::from(n))
1065 }
1066
1067 #[inline]
1068 fn from_i16(n: i16) -> Option<Self> {
1069 Self::from_i64(i64::from(n))
1070 }
1071
1072 #[inline]
1073 fn from_i32(n: i32) -> Option<Self> {
1074 Self::from_i64(i64::from(n))
1075 }
1076
1077 #[inline]
1078 fn from_i128(n: i128) -> Option<Self> {
1079 if n >= 0 {
1080 u64::try_from(n).ok().and_then(Self::from_u64)
1081 } else {
1082 i64::try_from(n).ok().and_then(Self::from_i64)
1083 }
1084 }
1085
1086 #[inline]
1087 fn from_usize(n: usize) -> Option<Self> {
1088 Self::from_u64(n as u64)
1089 }
1090
1091 #[inline]
1092 fn from_u8(n: u8) -> Option<Self> {
1093 Self::from_u64(u64::from(n))
1094 }
1095
1096 #[inline]
1097 fn from_u16(n: u16) -> Option<Self> {
1098 Self::from_u64(u64::from(n))
1099 }
1100
1101 #[inline]
1102 fn from_u32(n: u32) -> Option<Self> {
1103 Self::from_u64(u64::from(n))
1104 }
1105
1106 #[inline]
1107 fn from_u128(n: u128) -> Option<Self> {
1108 u64::try_from(n).ok().and_then(Self::from_u64)
1109 }
1110
1111 #[inline]
1112 fn from_f32(n: f32) -> Option<Self> {
1113 Self::from_f64(f64::from(n))
1114 }
1115
1116 #[inline]
1117 fn from_f64(n: f64) -> Option<Self> {
1118 match $crate::ToPrimitive::to_i64(&n) {
1119 Some(i) => Self::from_i64(i),
1120 None => $crate::ToPrimitive::to_u64(&n).and_then(Self::from_u64),
1121 }
1122 }
1123 }
1124 };
1125}
1126
1127#[cfg(test)]
1128mod default_tests {
1129 use crate::{FromPrimitive, ToPrimitive};
1130
1131 #[derive(Debug, PartialEq)]
1134 struct N(i32);
1135
1136 impl ToPrimitive for N {
1137 fn to_i64(&self) -> Option<i64> {
1138 Some(self.0 as i64)
1139 }
1140 fn to_u64(&self) -> Option<u64> {
1141 if self.0 >= 0 {
1142 Some(self.0 as u64)
1143 } else {
1144 None
1145 }
1146 }
1147 }
1148 impl FromPrimitive for N {
1149 fn from_i64(n: i64) -> Option<Self> {
1150 if n >= i32::MIN as i64 && n <= i32::MAX as i64 {
1151 Some(N(n as i32))
1152 } else {
1153 None
1154 }
1155 }
1156 fn from_u64(n: u64) -> Option<Self> {
1157 if n <= i32::MAX as u64 {
1158 Some(N(n as i32))
1159 } else {
1160 None
1161 }
1162 }
1163 }
1164
1165 #[test]
1166 fn minimal_impl_inherits_defaults() {
1167 assert_eq!(N(-5).to_i8(), Some(-5i8));
1169 assert_eq!(N(-5).to_u32(), None);
1170 assert_eq!(N(300).to_u8(), None);
1171 assert_eq!(N(300).to_i128(), Some(300i128));
1172 assert_eq!(N(300).to_f64(), Some(300.0));
1173 assert_eq!(N(300).to_f32(), Some(300.0));
1174 assert_eq!(N::from_i8(-5), Some(N(-5)));
1176 assert_eq!(N::from_u128(u128::MAX), None);
1177 assert_eq!(N::from_i128(-7), Some(N(-7)));
1178 assert_eq!(N::from_f64(300.7), Some(N(300)));
1179 assert_eq!(N::from_f32(42.0), Some(N(42)));
1180 }
1181
1182 #[derive(Debug, PartialEq)]
1185 struct U(u64);
1186 impl ToPrimitive for U {
1187 fn to_i64(&self) -> Option<i64> {
1188 if self.0 <= i64::MAX as u64 {
1189 Some(self.0 as i64)
1190 } else {
1191 None
1192 }
1193 }
1194 fn to_u64(&self) -> Option<u64> {
1195 Some(self.0)
1196 }
1197 }
1198 impl FromPrimitive for U {
1199 fn from_i64(n: i64) -> Option<Self> {
1200 if n >= 0 { Some(U(n as u64)) } else { None }
1201 }
1202 fn from_u64(n: u64) -> Option<Self> {
1203 Some(U(n))
1204 }
1205 }
1206
1207 #[derive(Debug, PartialEq)]
1209 struct UM(u64);
1210 crate::impl_to_primitive_minimal! {
1211 impl ToPrimitive for UM {
1212 to_i64 = |s: &UM| if s.0 <= i64::MAX as u64 { Some(s.0 as i64) } else { None },
1213 to_u64 = |s: &UM| Some(s.0),
1214 }
1215 }
1216 crate::impl_from_primitive_minimal! {
1217 impl FromPrimitive for UM {
1218 from_i64 = |n: i64| if n >= 0 { Some(UM(n as u64)) } else { None },
1219 from_u64 = |n: u64| Some(UM(n)),
1220 }
1221 }
1222
1223 #[test]
1224 fn i128_conversions_cover_high_u64_range() {
1225 let big = 1u64 << 63; let big_i = big as i128;
1227
1228 assert_eq!(U(big).to_i128(), Some(big_i));
1231 assert_eq!(U::from_i128(big_i), Some(U(big)));
1232 assert_eq!(UM(big).to_i128(), Some(big_i));
1234 assert_eq!(UM::from_i128(big_i), Some(UM(big)));
1235
1236 assert_eq!(U(5).to_i128(), Some(5));
1238 assert_eq!(U::from_i128(-1), None); assert_eq!(UM::from_i128(u64::MAX as i128 + 1), None); }
1241
1242 #[derive(Debug, PartialEq)]
1245 struct HugeF;
1246 impl ToPrimitive for HugeF {
1247 fn to_i64(&self) -> Option<i64> {
1248 None
1249 }
1250 fn to_u64(&self) -> Option<u64> {
1251 None
1252 }
1253 fn to_f64(&self) -> Option<f64> {
1254 Some(f64::MAX)
1255 }
1256 }
1257
1258 #[test]
1259 fn default_to_f32_saturates_overflow() {
1260 assert_eq!(HugeF.to_f32(), Some(f32::INFINITY));
1263 }
1264}