1use crate::prelude::*;
2use self::private::Sealed;
3
4macro_rules! from {
5 {
6 $losslessness:literal
7
8 $(#[$trait_meta:meta])*
9 trait $trait_name:ident
10
11 $(#[$fn_meta:meta])*
12 fn $fn_name:ident($type_name:ident)
13 } => {
14 #[doc = concat!(
15 "Trait for number types that can be converted from [`",
16 stringify!($type_name),
17 "`], ",
18 $losslessness
19 )]
20 #[doc = ""]
21 $(#[$trait_meta])*
22 pub trait $trait_name
23 where
24 Self: Sealed
25 {
26 #[doc = concat!("Convert from a [`", stringify!($type_name), "`] value")]
27 #[doc = ""]
28 $(#[$fn_meta])*
29 fn $fn_name(value: $type_name) -> Self;
30 }
31 };
32
33 {
34 impl $trait_name:ident::$fn_name:ident($type_name:ident)
35 $(
36 $(#[$meta:meta])*
37 $impl_type:ident
38 )*
39 } => {
40 $(
41 $(#[$meta])*
42 impl $trait_name for $impl_type {
43 #[expect(
44 clippy::as_conversions,
45 reason = "implementation detail of a more restrictive API"
46 )]
47 #[inline(always)]
48 fn $fn_name(value: $type_name) -> $impl_type { value as _ }
49 }
50 )*
51 };
52}
53
54macro_rules! into {
55 {
56 $losslessness:literal
57
58 $(#[$trait_meta:meta])*
59 trait $trait_name:ident
60
61 $(#[$fn_meta:meta])*
62 fn $fn_name:ident() -> $type_name:ident
63 } => {
64 #[doc = concat!(
65 "Trait for number types that can be converted into [`",
66 stringify!($type_name),
67 "`], ",
68 $losslessness
69 )]
70 #[doc = ""]
71 $(#[$trait_meta])*
72 pub trait $trait_name
73 where
74 Self: Sealed
75 {
76 #[doc = concat!("Convert into a [`", stringify!($type_name), "`] value")]
77 #[doc = ""]
78 $(#[$fn_meta])*
79 fn $fn_name(self) -> $type_name;
80 }
81 };
82
83 {
84 impl $trait_name:ident::$fn_name:ident() -> $type_name:ident
85 $(
86 $(#[$meta:meta])*
87 $impl_type:ident
88 )*
89 } => {
90 $(
91 $(#[$meta])*
92 impl $trait_name for $impl_type {
93 #[expect(
94 clippy::as_conversions,
95 reason = "implementation detail of a more restrictive API"
96 )]
97 #[inline(always)]
98 fn $fn_name(self) -> $type_name { self as _ }
99 }
100 )*
101 };
102}
103
104from! { "losslessly" trait FromU8 fn from_u8(u8) }
105from! { "losslessly" trait FromU16 fn from_u16(u16) }
106from! { "losslessly" trait FromU32 fn from_u32(u32) }
107from! { "losslessly" trait FromU64 fn from_u64(u64) }
108from! { "losslessly" trait FromU128 fn from_u128(u128) }
109from! { "losslessly" trait FromUsize fn from_usize(usize) }
110from! { "losslessly" trait FromI8 fn from_i8(i8) }
111from! { "losslessly" trait FromI16 fn from_i16(i16) }
112from! { "losslessly" trait FromI32 fn from_i32(i32) }
113from! { "losslessly" trait FromI64 fn from_i64(i64) }
114from! { "losslessly" trait FromI128 fn from_i128(i128) }
115from! { "losslessly" trait FromIsize fn from_isize(isize) }
116from! { "losslessly" trait FromF32 fn from_f32(f32) }
117from! { "losslessly" trait FromF64 fn from_f64(f64) }
118from! { "losslessly" trait FromBool fn from_bool(bool) }
119
120from! { "potentially lossily" trait FromU8Lossy fn from_u8_lossy(u8) }
121from! { "potentially lossily" trait FromU16Lossy fn from_u16_lossy(u16) }
122from! { "potentially lossily" trait FromU32Lossy fn from_u32_lossy(u32) }
123from! { "potentially lossily" trait FromU64Lossy fn from_u64_lossy(u64) }
124from! { "potentially lossily" trait FromU128Lossy fn from_u128_lossy(u128) }
125from! { "potentially lossily" trait FromUsizeLossy fn from_usize_lossy(usize) }
126from! { "potentially lossily" trait FromI8Lossy fn from_i8_lossy(i8) }
127from! { "potentially lossily" trait FromI16Lossy fn from_i16_lossy(i16) }
128from! { "potentially lossily" trait FromI32Lossy fn from_i32_lossy(i32) }
129from! { "potentially lossily" trait FromI64Lossy fn from_i64_lossy(i64) }
130from! { "potentially lossily" trait FromI128Lossy fn from_i128_lossy(i128) }
131from! { "potentially lossily" trait FromIsizeLossy fn from_isize_lossy(isize) }
132from! { "potentially lossily" trait FromF32Lossy fn from_f32_lossy(f32) }
133from! { "potentially lossily" trait FromF64Lossy fn from_f64_lossy(f64) }
134from! { "potentially lossily" trait FromBoolLossy fn from_bool_lossy(bool) }
135
136into! { "losslessly" trait IntoU8 fn into_u8() -> u8 }
137into! { "losslessly" trait IntoU16 fn into_u16() -> u16 }
138into! { "losslessly" trait IntoU32 fn into_u32() -> u32 }
139into! { "losslessly" trait IntoU64 fn into_u64() -> u64 }
140into! { "losslessly" trait IntoU128 fn into_u128() -> u128 }
141into! { "losslessly" trait IntoUsize fn into_usize() -> usize }
142into! { "losslessly" trait IntoI8 fn into_i8() -> i8 }
143into! { "losslessly" trait IntoI16 fn into_i16() -> i16 }
144into! { "losslessly" trait IntoI32 fn into_i32() -> i32 }
145into! { "losslessly" trait IntoI64 fn into_i64() -> i64 }
146into! { "losslessly" trait IntoI128 fn into_i128() -> i128 }
147into! { "losslessly" trait IntoIsize fn into_isize() -> isize }
148into! { "losslessly" trait IntoF32 fn into_f32() -> f32 }
149into! { "losslessly" trait IntoF64 fn into_f64() -> f64 }
150
151into! { "potentially lossily" trait IntoU8Lossy fn into_u8_lossy() -> u8 }
152into! { "potentially lossily" trait IntoU16Lossy fn into_u16_lossy() -> u16 }
153into! { "potentially lossily" trait IntoU32Lossy fn into_u32_lossy() -> u32 }
154into! { "potentially lossily" trait IntoU64Lossy fn into_u64_lossy() -> u64 }
155into! { "potentially lossily" trait IntoU128Lossy fn into_u128_lossy() -> u128 }
156into! { "potentially lossily" trait IntoUsizeLossy fn into_usize_lossy() -> usize }
157into! { "potentially lossily" trait IntoI8Lossy fn into_i8_lossy() -> i8 }
158into! { "potentially lossily" trait IntoI16Lossy fn into_i16_lossy() -> i16 }
159into! { "potentially lossily" trait IntoI32Lossy fn into_i32_lossy() -> i32 }
160into! { "potentially lossily" trait IntoI64Lossy fn into_i64_lossy() -> i64 }
161into! { "potentially lossily" trait IntoI128Lossy fn into_i128_lossy() -> i128 }
162into! { "potentially lossily" trait IntoIsizeLossy fn into_isize_lossy() -> isize }
163into! { "potentially lossily" trait IntoF32Lossy fn into_f32_lossy() -> f32 }
164into! { "potentially lossily" trait IntoF64Lossy fn into_f64_lossy() -> f64 }
165
166from! {
167 impl FromU8::from_u8(u8)
168 u8
169 u16 u32 u64 u128 usize
170 i16 i32 i64 i128 isize
171 f32 f64
172}
173
174from! {
175 impl FromU16::from_u16(u16)
176 u16
177 u32 u64 u128 usize
178 i32 i64 i128
179 #[cfg(any(
180 target_pointer_width = "32",
181 target_pointer_width = "64"
182 ))]
183 isize
184 f32 f64
185}
186
187from! {
188 impl FromU32::from_u32(u32)
189 u32
190 u64 u128
191 #[cfg(any(
192 target_pointer_width = "32",
193 target_pointer_width = "64"
194 ))]
195 usize
196 i64 i128
197 #[cfg(target_pointer_width = "64")]
198 isize
199 f64
200}
201
202from! {
203 impl FromU64::from_u64(u64)
204 u64
205 u128
206 #[cfg(target_pointer_width = "64")]
207 usize
208 i128
209}
210
211from! {
212 impl FromU128::from_u128(u128)
213 u128
214}
215
216from! {
217 impl FromUsize::from_usize(usize)
218 #[cfg(target_pointer_width = "16")]
219 u16
220 #[cfg(any(
221 target_pointer_width = "16",
222 target_pointer_width = "32"
223 ))]
224 u32
225 u64 u128 usize
226 #[cfg(target_pointer_width = "16")]
227 i32
228 #[cfg(any(
229 target_pointer_width = "16",
230 target_pointer_width = "32"
231 ))]
232 i64
233 i128
234 #[cfg(target_pointer_width = "16")]
235 f32
236 #[cfg(any(
237 target_pointer_width = "16",
238 target_pointer_width = "32"
239 ))]
240 f64
241}
242
243from! {
244 impl FromI8::from_i8(i8)
245 i8
246 i16 i32 i64 i128 isize
247 f32 f64
248}
249
250from! {
251 impl FromI16::from_i16(i16)
252 i16
253 i32 i64 i128 isize
254 f32 f64
255}
256
257from! {
258 impl FromI32::from_i32(i32)
259 i32
260 i64 i128
261 #[cfg(any(
262 target_pointer_width = "32",
263 target_pointer_width = "64"
264 ))]
265 isize
266 f64
267}
268
269from! {
270 impl FromI64::from_i64(i64)
271 i64
272 i128
273 #[cfg(target_pointer_width = "64")]
274 isize
275}
276
277from! {
278 impl FromI128::from_i128(i128)
279 i128
280}
281
282from! {
283 impl FromIsize::from_isize(isize)
284 #[cfg(target_pointer_width = "16")]
285 i16
286 #[cfg(any(
287 target_pointer_width = "16",
288 target_pointer_width = "32"
289 ))]
290 i32
291 i64 i128 isize
292 #[cfg(target_pointer_width = "16")]
293 f32
294 #[cfg(any(
295 target_pointer_width = "16",
296 target_pointer_width = "32"
297 ))]
298 f64
299}
300
301from! {
302 impl FromF32::from_f32(f32)
303 f32 f64
304}
305
306from! {
307 impl FromF64::from_f64(f64)
308 f64
309}
310
311from! {
312 impl FromBool::from_bool(bool)
313 u8 u16 u32 u64 u128 usize
314 i8 i16 i32 i64 i128 isize
315}
316
317impl FromBool for f32 {
318 #[expect(
319 clippy::as_conversions,
320 reason = "implementation detail of a more restrictive API"
321 )]
322 #[expect(
323 clippy::inline_always,
324 reason = "simple cast op"
325 )]
326 #[inline(always)]
327 fn from_bool(value: bool) -> f32 { value as u32 as _ }
330}
331
332impl FromBool for f64 {
333 #[expect(
334 clippy::as_conversions,
335 reason = "implementation detail of a more restrictive API"
336 )]
337 #[expect(
338 clippy::inline_always,
339 reason = "simple cast op"
340 )]
341 #[inline(always)]
342 fn from_bool(value: bool) -> f64 { value as u64 as _ }
345}
346
347from! {
348 impl FromU8Lossy::from_u8_lossy(u8)
349 u8 u16 u32 u64 u128 usize
350 i8 i16 i32 i64 i128 isize
351 f32 f64
352}
353
354from! {
355 impl FromU16Lossy::from_u16_lossy(u16)
356 u8 u16 u32 u64 u128 usize
357 i8 i16 i32 i64 i128 isize
358 f32 f64
359}
360
361from! {
362 impl FromU32Lossy::from_u32_lossy(u32)
363 u8 u16 u32 u64 u128 usize
364 i8 i16 i32 i64 i128 isize
365 f32 f64
366}
367
368from! {
369 impl FromU64Lossy::from_u64_lossy(u64)
370 u8 u16 u32 u64 u128 usize
371 i8 i16 i32 i64 i128 isize
372 f32 f64
373}
374
375from! {
376 impl FromU128Lossy::from_u128_lossy(u128)
377 u8 u16 u32 u64 u128 usize
378 i8 i16 i32 i64 i128 isize
379 f32 f64
380}
381
382from! {
383 impl FromUsizeLossy::from_usize_lossy(usize)
384 u8 u16 u32 u64 u128 usize
385 i8 i16 i32 i64 i128 isize
386 f32 f64
387}
388
389from! {
390 impl FromI8Lossy::from_i8_lossy(i8)
391 u8 u16 u32 u64 u128 usize
392 i8 i16 i32 i64 i128 isize
393 f32 f64
394}
395
396from! {
397 impl FromI16Lossy::from_i16_lossy(i16)
398 u8 u16 u32 u64 u128 usize
399 i8 i16 i32 i64 i128 isize
400 f32 f64
401}
402
403from! {
404 impl FromI32Lossy::from_i32_lossy(i32)
405 u8 u16 u32 u64 u128 usize
406 i8 i16 i32 i64 i128 isize
407 f32 f64
408}
409
410from! {
411 impl FromI64Lossy::from_i64_lossy(i64)
412 u8 u16 u32 u64 u128 usize
413 i8 i16 i32 i64 i128 isize
414 f32 f64
415}
416
417from! {
418 impl FromI128Lossy::from_i128_lossy(i128)
419 u8 u16 u32 u64 u128 usize
420 i8 i16 i32 i64 i128 isize
421 f32 f64
422}
423
424from! {
425 impl FromIsizeLossy::from_isize_lossy(isize)
426 u8 u16 u32 u64 u128 usize
427 i8 i16 i32 i64 i128 isize
428 f32 f64
429}
430
431from! {
432 impl FromF32Lossy::from_f32_lossy(f32)
433 u8 u16 u32 u64 u128 usize
434 i8 i16 i32 i64 i128 isize
435 f32 f64
436}
437
438from! {
439 impl FromF64Lossy::from_f64_lossy(f64)
440 u8 u16 u32 u64 u128 usize
441 i8 i16 i32 i64 i128 isize
442 f32 f64
443}
444
445from! {
446 impl FromBoolLossy::from_bool_lossy(bool)
447 u8 u16 u32 u64 u128 usize
448 i8 i16 i32 i64 i128 isize
449}
450
451impl FromBoolLossy for f32 {
452 #[expect(
453 clippy::as_conversions,
454 reason = "implementation detail of a more restrictive API"
455 )]
456 #[expect(
457 clippy::inline_always,
458 reason = "simple cast op"
459 )]
460 #[inline(always)]
461 fn from_bool_lossy(value: bool) -> f32 { value as u32 as _ }
464}
465
466impl FromBoolLossy for f64 {
467 #[expect(
468 clippy::as_conversions,
469 reason = "implementation detail of a more restrictive API"
470 )]
471 #[expect(
472 clippy::inline_always,
473 reason = "simple cast op"
474 )]
475 #[inline(always)]
476 fn from_bool_lossy(value: bool) -> f64 { value as u64 as _ }
479}
480
481into! {
482 impl IntoU8::into_u8() -> u8
483 u8
484 bool
485}
486
487into! {
488 impl IntoU16::into_u16() -> u16
489 u8 u16
490 #[cfg(target_pointer_width = "16")]
491 usize
492 bool
493}
494
495into! {
496 impl IntoU32::into_u32() -> u32
497 u8 u16 u32
498 #[cfg(any(
499 target_pointer_width = "16",
500 target_pointer_width = "32"
501 ))]
502 usize
503 bool
504}
505
506into! {
507 impl IntoU64::into_u64() -> u64
508 u8 u16 u32 u64 usize
509 bool
510}
511
512into! {
513 impl IntoU128::into_u128() -> u128
514 u8 u16 u32 u64 u128 usize
515 bool
516}
517
518into! {
519 impl IntoUsize::into_usize() -> usize
520 u8 u16
521 #[cfg(any(
522 target_pointer_width = "32",
523 target_pointer_width = "64"
524 ))]
525 u32
526 #[cfg(target_pointer_width = "64")]
527 u64
528 usize
529 bool
530}
531
532into! {
533 impl IntoI8::into_i8() -> i8
534 i8
535 bool
536}
537
538into! {
539 impl IntoI16::into_i16() -> i16
540 u8
541 i8 i16
542 #[cfg(target_pointer_width = "16")]
543 isize
544 bool
545}
546
547into! {
548 impl IntoI32::into_i32() -> i32
549 u8 u16
550 #[cfg(target_pointer_width = "16")]
551 usize
552 i8 i16 i32
553 #[cfg(any(
554 target_pointer_width = "16",
555 target_pointer_width = "32"
556 ))]
557 isize
558 bool
559}
560
561into! {
562 impl IntoI64::into_i64() -> i64
563 u8 u16 u32
564 #[cfg(any(
565 target_pointer_width = "16",
566 target_pointer_width = "32"
567 ))]
568 usize
569 i8 i16 i32 i64 isize
570 bool
571}
572
573into! {
574 impl IntoI128::into_i128() -> i128
575 u8 u16 u32 u64 usize
576 i8 i16 i32 i64 i128 isize
577 bool
578}
579
580into! {
581 impl IntoIsize::into_isize() -> isize
582 u8
583 #[cfg(any(
584 target_pointer_width = "32",
585 target_pointer_width = "64"
586 ))]
587 u16
588 #[cfg(target_pointer_width = "64")]
589 u32
590 i8 i16
591 #[cfg(any(
592 target_pointer_width = "32",
593 target_pointer_width = "64"
594 ))]
595 i32
596 #[cfg(target_pointer_width = "64")]
597 i64
598 isize
599 bool
600}
601
602into! {
603 impl IntoF32::into_f32() -> f32
604 u8 u16
605 #[cfg(target_pointer_width = "16")]
606 usize
607 i8 i16
608 #[cfg(target_pointer_width = "16")]
609 isize
610 f32
611}
612
613impl IntoF32 for bool {
614 #[expect(
615 clippy::as_conversions,
616 reason = "implementation detail of a more restrictive API"
617 )]
618 #[expect(
619 clippy::inline_always,
620 reason = "simple cast op"
621 )]
622 #[inline(always)]
623 fn into_f32(self) -> f32 { self as u32 as _ }
624}
625
626into! {
627 impl IntoF64::into_f64() -> f64
628 u8 u16 u32
629 #[cfg(any(
630 target_pointer_width = "16",
631 target_pointer_width = "32"
632 ))]
633 usize
634 i8 i16 i32
635 #[cfg(any(
636 target_pointer_width = "16",
637 target_pointer_width = "32"
638 ))]
639 isize
640 f32 f64
641}
642
643impl IntoF64 for bool {
644 #[expect(
645 clippy::as_conversions,
646 reason = "implementation detail of a more restrictive API"
647 )]
648 #[expect(
649 clippy::inline_always,
650 reason = "simple cast op"
651 )]
652 #[inline(always)]
653 fn into_f64(self) -> f64 { self as u64 as _ }
656}
657
658into! {
659 impl IntoU8Lossy::into_u8_lossy() -> u8
660 u8 u16 u32 u64 u128 usize
661 i8 i16 i32 i64 i128 isize
662 f32 f64
663 bool
664}
665
666into! {
667 impl IntoU16Lossy::into_u16_lossy() -> u16
668 u8 u16 u32 u64 u128 usize
669 i8 i16 i32 i64 i128 isize
670 f32 f64
671 bool
672}
673
674into! {
675 impl IntoU32Lossy::into_u32_lossy() -> u32
676 u8 u16 u32 u64 u128 usize
677 i8 i16 i32 i64 i128 isize
678 f32 f64
679 bool
680}
681
682into! {
683 impl IntoU64Lossy::into_u64_lossy() -> u64
684 u8 u16 u32 u64 u128 usize
685 i8 i16 i32 i64 i128 isize
686 f32 f64
687 bool
688}
689
690into! {
691 impl IntoU128Lossy::into_u128_lossy() -> u128
692 u8 u16 u32 u64 u128 usize
693 i8 i16 i32 i64 i128 isize
694 f32 f64
695 bool
696}
697
698into! {
699 impl IntoUsizeLossy::into_usize_lossy() -> usize
700 u8 u16 u32 u64 u128 usize
701 i8 i16 i32 i64 i128 isize
702 f32 f64
703 bool
704}
705
706into! {
707 impl IntoI8Lossy::into_i8_lossy() -> i8
708 u8 u16 u32 u64 u128 usize
709 i8 i16 i32 i64 i128 isize
710 f32 f64
711 bool
712}
713
714into! {
715 impl IntoI16Lossy::into_i16_lossy() -> i16
716 u8 u16 u32 u64 u128 usize
717 i8 i16 i32 i64 i128 isize
718 f32 f64
719 bool
720}
721
722into! {
723 impl IntoI32Lossy::into_i32_lossy() -> i32
724 u8 u16 u32 u64 u128 usize
725 i8 i16 i32 i64 i128 isize
726 f32 f64
727 bool
728}
729
730into! {
731 impl IntoI64Lossy::into_i64_lossy() -> i64
732 u8 u16 u32 u64 u128 usize
733 i8 i16 i32 i64 i128 isize
734 f32 f64
735 bool
736}
737
738into! {
739 impl IntoI128Lossy::into_i128_lossy() -> i128
740 u8 u16 u32 u64 u128 usize
741 i8 i16 i32 i64 i128 isize
742 f32 f64
743 bool
744}
745
746into! {
747 impl IntoIsizeLossy::into_isize_lossy() -> isize
748 u8 u16 u32 u64 u128 usize
749 i8 i16 i32 i64 i128 isize
750 f32 f64
751 bool
752}
753
754into! {
755 impl IntoF32Lossy::into_f32_lossy() -> f32
756 u8 u16 u32 u64 u128 usize
757 i8 i16 i32 i64 i128 isize
758 f32 f64
759}
760
761impl IntoF32Lossy for bool {
762 #[expect(
763 clippy::as_conversions,
764 reason = "implementation detail of a more restrictive API"
765 )]
766 #[expect(
767 clippy::inline_always,
768 reason = "simple cast op"
769 )]
770 #[inline(always)]
771 fn into_f32_lossy(self) -> f32 { self as u32 as _ }
774}
775
776into! {
777 impl IntoF64Lossy::into_f64_lossy() -> f64
778 u8 u16 u32 u64 u128 usize
779 i8 i16 i32 i64 i128 isize
780 f32 f64
781}
782
783impl IntoF64Lossy for bool {
784 #[expect(
785 clippy::as_conversions,
786 reason = "implementation detail of a more restrictive API"
787 )]
788 #[expect(
789 clippy::inline_always,
790 reason = "simple cast op"
791 )]
792 #[inline(always)]
793 fn into_f64_lossy(self) -> f64 { self as u64 as _ }
794}
795
796pub trait FromNum<Num>
797where
798 Self: Sealed
799{
800 fn from_num(num: Num) -> Self;
801}
802
803pub trait FromNumLossy<Num>
804where
805 Self: Sealed
806{
807 fn from_num_lossy(num: Num) -> Self;
808}
809
810pub trait IntoNum<Num>
811where
812 Self: Sealed
813{
814 fn into_num(self) -> Num;
815}
816
817pub trait IntoNumLossy<Num>
818where
819 Self: Sealed
820{
821 fn into_num_lossy(self) -> Num;
822}
823
824impl<NFrom, NInto> FromNumLossy<NFrom> for NInto
825where
826 NInto: FromNum<NFrom>
827{
828 #[inline]
829 fn from_num_lossy(num: NFrom) -> Self {
830 NInto::from_num(num)
831 }
832}
833
834impl<NFrom, NInto> IntoNum<NInto> for NFrom
835where
836 NFrom: Sealed,
837 NInto: FromNum<NFrom>
838{
839 #[inline]
840 fn into_num(self) -> NInto {
841 NInto::from_num(self)
842 }
843}
844
845impl<NFrom, NInto> IntoNumLossy<NInto> for NFrom
846where
847 NFrom: Sealed,
848 NInto: FromNumLossy<NFrom>
849{
850 #[inline]
851 fn into_num_lossy(self) -> NInto {
852 NInto::from_num_lossy(self)
853 }
854}
855
856macro_rules! impl_generic_num_conversions {
857 {
858 for $to:ident
859 lossless $trait_lossless:ident::$fn_lossless:ident
860 lossy $trait_lossy:ident::$fn_lossy:ident
861 $($(#[$meta:meta])* $from:ident $lossness:ident)*
862 } => {
863 $(
864 impl_generic_num_conversions! {
865 @impl
866 $trait_lossless $fn_lossless
867 $trait_lossy $fn_lossy
868 $(#[$meta])* $from $to $lossness
869 }
870 )*
871 };
872
873 {
874 @impl
875 $trait_lossless:ident $fn_lossless:ident
876 $trait_lossy:ident $fn_lossy:ident
877 $(#[$meta:meta])* $from:ident $to:ident lossless
878 } => {
879 impl_generic_num_conversions! {
880 @impl
881 $(#[$meta])* $from $to
882 FromNum from_num
883 $trait_lossless $fn_lossless
884 }
885 };
886
887 {
888 @impl
889 $trait_lossless:ident $fn_lossless:ident
890 $trait_lossy:ident $fn_lossy:ident
891 $(#[$meta:meta])* $from:ident $to:ident lossy
892 } => {
893 impl_generic_num_conversions! {
894 @impl
895 $(#[$meta])* $from $to
896 FromNumLossy from_num_lossy
897 $trait_lossy $fn_lossy
898 }
899 };
900
901 {
902 @impl
903 $(#[$meta:meta])*
904 $from:ident $to:ident
905 $generic_trait:ident $generic_fn:ident
906 $trait_name:ident $fn_name:ident
907 } => {
908 $(#[$meta])*
909 impl $generic_trait<$from> for $to {
910 #[inline(always)]
911 fn $generic_fn(num: $from) -> $to {
912 <$from as $trait_name>::$fn_name(num)
913 }
914 }
915 };
916}
917
918impl_generic_num_conversions! {
919 for u8
920 lossless IntoU8::into_u8
921 lossy IntoU8Lossy::into_u8_lossy
922
923 u8 lossless
924 u16 lossy
925 u32 lossy
926 u64 lossy
927 u128 lossy
928 usize lossy
929 i8 lossy
930 i16 lossy
931 i32 lossy
932 i64 lossy
933 i128 lossy
934 isize lossy
935 f32 lossy
936 f64 lossy
937 bool lossless
938}
939
940impl_generic_num_conversions! {
941 for u16
942 lossless IntoU16::into_u16
943 lossy IntoU16Lossy::into_u16_lossy
944
945 u8 lossless
946 u16 lossless
947 u32 lossy
948 u64 lossy
949 u128 lossy
950 #[cfg(target_pointer_width = "16")]
951 usize lossless
952 #[cfg(any(
953 target_pointer_width = "32",
954 target_pointer_width = "64"
955 ))]
956 usize lossy
957 i8 lossy
958 i16 lossy
959 i32 lossy
960 i64 lossy
961 i128 lossy
962 isize lossy
963 f32 lossy
964 f64 lossy
965 bool lossless
966}
967
968impl_generic_num_conversions! {
969 for u32
970 lossless IntoU32::into_u32
971 lossy IntoU32Lossy::into_u32_lossy
972
973 u8 lossless
974 u16 lossless
975 u32 lossless
976 u64 lossy
977 u128 lossy
978 #[cfg(any(
979 target_pointer_width = "16",
980 target_pointer_width = "32"
981 ))]
982 usize lossless
983 #[cfg(target_pointer_width = "64")]
984 usize lossy
985 i8 lossy
986 i16 lossy
987 i32 lossy
988 i64 lossy
989 i128 lossy
990 isize lossy
991 f32 lossy
992 f64 lossy
993 bool lossless
994}
995
996impl_generic_num_conversions! {
997 for u64
998 lossless IntoU64::into_u64
999 lossy IntoU64Lossy::into_u64_lossy
1000
1001 u8 lossless
1002 u16 lossless
1003 u32 lossless
1004 u64 lossless
1005 u128 lossy
1006 usize lossless
1007 i8 lossy
1008 i16 lossy
1009 i32 lossy
1010 i64 lossy
1011 i128 lossy
1012 isize lossy
1013 f32 lossy
1014 f64 lossy
1015 bool lossless
1016}
1017
1018impl_generic_num_conversions! {
1019 for u128
1020 lossless IntoU128::into_u128
1021 lossy IntoU128Lossy::into_u128_lossy
1022
1023 u8 lossless
1024 u16 lossless
1025 u32 lossless
1026 u64 lossless
1027 u128 lossless
1028 usize lossless
1029 i8 lossy
1030 i16 lossy
1031 i32 lossy
1032 i64 lossy
1033 i128 lossy
1034 isize lossy
1035 f32 lossy
1036 f64 lossy
1037 bool lossless
1038}
1039
1040impl_generic_num_conversions! {
1041 for usize
1042 lossless IntoUsize::into_usize
1043 lossy IntoUsizeLossy::into_usize_lossy
1044
1045 u8 lossless
1046 u16 lossless
1047 #[cfg(target_pointer_width = "16")]
1048 u32 lossy
1049 #[cfg(any(
1050 target_pointer_width = "32",
1051 target_pointer_width = "64"
1052 ))]
1053 u32 lossless
1054 #[cfg(any(
1055 target_pointer_width = "16",
1056 target_pointer_width = "32"
1057 ))]
1058 u64 lossy
1059 #[cfg(target_pointer_width = "64")]
1060 u64 lossless
1061 u128 lossy
1062 usize lossless
1063 i8 lossy
1064 i16 lossy
1065 i32 lossy
1066 i64 lossy
1067 i128 lossy
1068 isize lossy
1069 f32 lossy
1070 f64 lossy
1071 bool lossless
1072}
1073
1074impl_generic_num_conversions! {
1075 for i8
1076 lossless IntoI8::into_i8
1077 lossy IntoI8Lossy::into_i8_lossy
1078
1079 u8 lossy
1080 u16 lossy
1081 u32 lossy
1082 u64 lossy
1083 u128 lossy
1084 usize lossy
1085 i8 lossless
1086 i16 lossy
1087 i32 lossy
1088 i64 lossy
1089 i128 lossy
1090 isize lossy
1091 f32 lossy
1092 f64 lossy
1093 bool lossless
1094}
1095
1096impl_generic_num_conversions! {
1097 for i16
1098 lossless IntoI16::into_i16
1099 lossy IntoI16Lossy::into_i16_lossy
1100
1101 u8 lossless
1102 u16 lossy
1103 u32 lossy
1104 u64 lossy
1105 u128 lossy
1106 usize lossy
1107 i8 lossless
1108 i16 lossless
1109 i32 lossy
1110 i64 lossy
1111 i128 lossy
1112 #[cfg(target_pointer_width = "16")]
1113 isize lossless
1114 #[cfg(any(
1115 target_pointer_width = "32",
1116 target_pointer_width = "64"
1117 ))]
1118 isize lossy
1119 f32 lossy
1120 f64 lossy
1121 bool lossless
1122}
1123
1124impl_generic_num_conversions! {
1125 for i32
1126 lossless IntoI32::into_i32
1127 lossy IntoI32Lossy::into_i32_lossy
1128
1129 u8 lossless
1130 u16 lossless
1131 u32 lossy
1132 u64 lossy
1133 u128 lossy
1134 #[cfg(target_pointer_width = "16")]
1135 usize lossless
1136 #[cfg(any(
1137 target_pointer_width = "32",
1138 target_pointer_width = "64"
1139 ))]
1140 usize lossy
1141 i8 lossless
1142 i16 lossless
1143 i32 lossless
1144 i64 lossy
1145 i128 lossy
1146 #[cfg(any(
1147 target_pointer_width = "16",
1148 target_pointer_width = "32"
1149 ))]
1150 isize lossless
1151 #[cfg(target_pointer_width = "64")]
1152 isize lossy
1153 f32 lossy
1154 f64 lossy
1155 bool lossless
1156}
1157
1158impl_generic_num_conversions! {
1159 for i64
1160 lossless IntoI64::into_i64
1161 lossy IntoI64Lossy::into_i64_lossy
1162
1163 u8 lossless
1164 u16 lossless
1165 u32 lossless
1166 u64 lossy
1167 u128 lossy
1168 #[cfg(any(
1169 target_pointer_width = "16",
1170 target_pointer_width = "32"
1171 ))]
1172 usize lossless
1173 #[cfg(target_pointer_width = "64")]
1174 usize lossy
1175 i8 lossless
1176 i16 lossless
1177 i32 lossless
1178 i64 lossless
1179 i128 lossy
1180 isize lossless
1181 f32 lossy
1182 f64 lossy
1183 bool lossless
1184}
1185
1186impl_generic_num_conversions! {
1187 for i128
1188 lossless IntoI128::into_i128
1189 lossy IntoI128Lossy::into_i128_lossy
1190
1191 u8 lossless
1192 u16 lossless
1193 u32 lossless
1194 u64 lossless
1195 u128 lossy
1196 usize lossless
1197 i8 lossless
1198 i16 lossless
1199 i32 lossless
1200 i64 lossless
1201 i128 lossless
1202 isize lossless
1203 f32 lossy
1204 f64 lossy
1205 bool lossless
1206}
1207
1208impl_generic_num_conversions! {
1209 for isize
1210 lossless IntoIsize::into_isize
1211 lossy IntoIsizeLossy::into_isize_lossy
1212
1213 u8 lossless
1214 #[cfg(target_pointer_width = "16")]
1215 u16 lossy
1216 #[cfg(any(
1217 target_pointer_width = "32",
1218 target_pointer_width = "64"
1219 ))]
1220 u16 lossless
1221 #[cfg(any(
1222 target_pointer_width = "16",
1223 target_pointer_width = "32"
1224 ))]
1225 u32 lossy
1226 #[cfg(target_pointer_width = "64")]
1227 u32 lossless
1228 u64 lossy
1229 u128 lossy
1230 usize lossy
1231 i8 lossless
1232 i16 lossless
1233 #[cfg(target_pointer_width = "16")]
1234 i32 lossy
1235 #[cfg(any(
1236 target_pointer_width = "32",
1237 target_pointer_width = "64"
1238 ))]
1239 i32 lossless
1240 #[cfg(any(
1241 target_pointer_width = "16",
1242 target_pointer_width = "32"
1243 ))]
1244 i64 lossy
1245 #[cfg(target_pointer_width = "64")]
1246 i64 lossless
1247 i128 lossy
1248 isize lossless
1249 f32 lossy
1250 f64 lossy
1251 bool lossless
1252}
1253
1254impl_generic_num_conversions! {
1255 for f32
1256 lossless IntoF32::into_f32
1257 lossy IntoF32Lossy::into_f32_lossy
1258
1259 u8 lossless
1260 u16 lossless
1261 u32 lossy
1262 u64 lossy
1263 u128 lossy
1264 usize lossy
1265 i8 lossless
1266 i16 lossless
1267 i32 lossy
1268 i64 lossy
1269 i128 lossy
1270 isize lossy
1271 f32 lossless
1272 f64 lossy
1273 bool lossless
1274}
1275
1276impl_generic_num_conversions! {
1277 for f64
1278 lossless IntoF64::into_f64
1279 lossy IntoF64Lossy::into_f64_lossy
1280
1281 u8 lossless
1282 u16 lossless
1283 u32 lossless
1284 u64 lossy
1285 u128 lossy
1286 usize lossy
1287 i8 lossless
1288 i16 lossless
1289 i32 lossless
1290 i64 lossy
1291 i128 lossy
1292 isize lossy
1293 f32 lossless
1294 f64 lossless
1295 bool lossless
1296}
1297
1298pub trait ArrayConversions<const N: usize>
1299where
1300 Self: Sealed
1301{
1302 fn into_le_bytes(self) -> [u8; N];
1303 fn into_be_bytes(self) -> [u8; N];
1304 fn into_ne_bytes(self) -> [u8; N];
1305 fn from_le_bytes(bytes: [u8; N]) -> Self;
1306 fn from_be_bytes(bytes: [u8; N]) -> Self;
1307 fn from_ne_bytes(bytes: [u8; N]) -> Self;
1308}
1309
1310macro_rules! impl_array_conversions {
1311 { $($(#[$meta:meta])* $num:ident $bytes:literal)* } => {
1312 $(
1313 $(#[$meta])*
1314 impl ArrayConversions<$bytes> for $num {
1315 #[inline(always)]
1316 fn into_le_bytes(self) -> [u8; $bytes] { $num::to_le_bytes(self) }
1317
1318 #[inline(always)]
1319 fn into_be_bytes(self) -> [u8; $bytes] { $num::to_be_bytes(self) }
1320
1321 #[inline(always)]
1322 fn into_ne_bytes(self) -> [u8; $bytes] { $num::to_ne_bytes(self) }
1323
1324 #[inline(always)]
1325 fn from_le_bytes(bytes: [u8; $bytes]) -> $num { $num::from_le_bytes(bytes) }
1326
1327 #[inline(always)]
1328 fn from_be_bytes(bytes: [u8; $bytes]) -> $num { $num::from_be_bytes(bytes) }
1329
1330 #[inline(always)]
1331 fn from_ne_bytes(bytes: [u8; $bytes]) -> $num { $num::from_ne_bytes(bytes) }
1332 }
1333 )*
1334 }
1335}
1336
1337impl_array_conversions! {
1338 u8 1
1339 u16 2
1340 u32 4
1341 u64 8
1342 u128 16
1343
1344 i8 1
1345 i16 2
1346 i32 4
1347 i64 8
1348 i128 16
1349
1350 f32 4
1351 f64 8
1352
1353 #[cfg(target_pointer_width = "16")]
1354 usize 2
1355 #[cfg(target_pointer_width = "16")]
1356 isize 2
1357
1358 #[cfg(target_pointer_width = "32")]
1359 usize 4
1360 #[cfg(target_pointer_width = "32")]
1361 isize 4
1362
1363 #[cfg(target_pointer_width = "64")]
1364 usize 8
1365 #[cfg(target_pointer_width = "64")]
1366 isize 8
1367}
1368
1369pub trait Endian<Num, const N: usize>
1370where
1371 Self: Sealed,
1372 Num: ArrayConversions<N>
1373{
1374 fn from_bytes(bytes: [u8; N]) -> Num;
1375 fn into_bytes(num: Num) -> [u8; N];
1376}
1377
1378macro_rules! decl_endian_structs {
1379 { $($endian_str:literal $struct:ident $from:ident $into:ident)* } => {
1380 $(
1381 #[doc = $endian_str]
1383 pub struct $struct {
1385 __private: ()
1386 }
1387
1388 impl Sealed for $struct {}
1389
1390 impl<Num, const N: usize> Endian<Num, N> for $struct
1391 where
1392 Num: ArrayConversions<N>
1393 {
1394 #[inline]
1395 fn from_bytes(bytes: [u8; N]) -> Num {
1396 Num::$from(bytes)
1397 }
1398
1399 #[inline]
1400 fn into_bytes(num: Num) -> [u8; N] {
1401 Num::$into(num)
1402 }
1403 }
1404 )*
1405 }
1406}
1407
1408decl_endian_structs! {
1409 "little endian" EndianLittle from_le_bytes into_le_bytes
1410 "big endian" EndianBig from_be_bytes into_be_bytes
1411 "native endian" EndianNative from_ne_bytes into_ne_bytes
1412}
1413
1414pub trait IntSignedness
1415where
1416 Self: Sealed
1417{
1418 const SIGNED: bool;
1419}
1420
1421macro_rules! impl_int_signedness {
1422 { $($int:ident $signed:literal)* } => {
1423 $(
1424 impl IntSignedness for $int {
1425 const SIGNED: bool = $signed;
1426 }
1427 )*
1428 }
1429}
1430
1431impl_int_signedness! {
1432 u8 false
1433 u16 false
1434 u32 false
1435 u64 false
1436 u128 false
1437 usize false
1438 i8 true
1439 i16 true
1440 i32 true
1441 i64 true
1442 i128 true
1443 isize true
1444}
1445
1446pub trait IntUnsigned
1447where
1448 Self: Sealed,
1449 Self::Signed: IntSigned<Unsigned = Self>
1450{
1451 type Signed;
1452
1453 fn into_signed(self) -> Self::Signed;
1454}
1455
1456pub trait IntSigned
1457where
1458 Self: Sealed,
1459 Self::Unsigned: IntUnsigned<Signed = Self>
1460{
1461 type Unsigned;
1462
1463 fn into_unsigned(self) -> Self::Unsigned;
1464}
1465
1466macro_rules! impl_int_signed_and_unsigned {
1467 { $($unsigned:ident $signed:ident)* } => {
1468 $(
1469 impl IntUnsigned for $unsigned {
1470 type Signed = $signed;
1471
1472 #[expect(
1473 clippy::as_conversions,
1474 reason = "implementation detail of a more restrictive API"
1475 )]
1476 #[inline(always)]
1477 fn into_signed(self) -> $signed { self as _ }
1478 }
1479
1480 impl IntSigned for $signed {
1481 type Unsigned = $unsigned;
1482
1483 #[expect(
1484 clippy::as_conversions,
1485 reason = "implementation detail of a more restrictive API"
1486 )]
1487 #[inline(always)]
1488 fn into_unsigned(self) -> $unsigned { self as _ }
1489 }
1490 )*
1491 }
1492}
1493
1494impl_int_signed_and_unsigned! {
1495 u8 i8
1496 u16 i16
1497 u32 i32
1498 u64 i64
1499 u128 i128
1500 usize isize
1501}
1502
1503macro_rules! op_trait {
1504 {
1505 $(#[$trait_meta:meta])*
1506 trait $trait_name:ident
1507 $(#[$fn_meta:meta])*
1508 fn $fn_name:ident(rhs)
1509 $(
1510 $(#[$output_meta:meta])*
1511 type Output
1512 )?
1513 } => {
1514 $(#[$trait_meta])*
1515 pub trait $trait_name<R>
1516 where
1517 Self: Sealed,
1518 R: Sealed
1519 {
1520 $($(#[$output_meta])*)?
1521 type Output;
1522
1523 $(#[$fn_meta])*
1524 fn $fn_name(self, rhs: R) -> Self::Output;
1525 }
1526 };
1527
1528 {
1529 $(#[$trait_meta:meta])*
1530 trait $trait_name:ident
1531 $(#[$fn_meta:meta])*
1532 fn $fn_name:ident()
1533 $(
1534 $(#[$output_meta:meta])*
1535 type Output
1536 )?
1537 } => {
1538 $(#[$trait_meta])*
1539 pub trait $trait_name
1540 where
1541 Self: Sealed
1542 {
1543 $($(#[$output_meta])*)?
1544 type Output;
1545
1546 $(#[$fn_meta])*
1547 fn $fn_name(self) -> Self::Output;
1548 }
1549 };
1550
1551 {
1552 $(#[$trait_meta:meta])*
1553 trait(option) $trait_name:ident
1554 $(#[$fn_meta:meta])*
1555 fn $fn_name:ident(rhs)
1556 $(
1557 $(#[$output_meta:meta])*
1558 type Output
1559 )?
1560 } => {
1561 $(#[$trait_meta])*
1562 pub trait $trait_name<R>
1563 where
1564 Self: Sealed,
1565 R: Sealed
1566 {
1567 $($(#[$output_meta])*)?
1568 type Output;
1569
1570 $(#[$fn_meta])*
1571 fn $fn_name(self, rhs: R) -> Option<Self::Output>;
1572 }
1573 };
1574
1575 {
1576 $(#[$trait_meta:meta])*
1577 trait(option) $trait_name:ident
1578 $(#[$fn_meta:meta])*
1579 fn $fn_name:ident()
1580 $(
1581 $(#[$output_meta:meta])*
1582 type Output
1583 )?
1584 } => {
1585 $(#[$trait_meta])*
1586 pub trait $trait_name
1587 where
1588 Self: Sealed
1589 {
1590 $($(#[$output_meta])*)?
1591 type Output;
1592
1593 $(#[$fn_meta])*
1594 fn $fn_name(self) -> Option<Self::Output>;
1595 }
1596 };
1597
1598 {
1599 $(#[$trait_meta:meta])*
1600 trait(tuple) $trait_name:ident
1601 $(#[$fn_meta:meta])*
1602 fn $fn_name:ident(rhs)
1603 $(
1604 $(#[$output_meta:meta])*
1605 type Output
1606 )?
1607 } => {
1608 $(#[$trait_meta])*
1609 pub trait $trait_name<R>
1610 where
1611 Self: Sealed,
1612 R: Sealed
1613 {
1614 $($(#[$output_meta])*)?
1615 type Output;
1616
1617 $(#[$fn_meta])*
1618 fn $fn_name(self, rhs: R) -> (Self::Output, bool);
1619 }
1620 };
1621
1622 {
1623 $(#[$trait_meta:meta])*
1624 trait(tuple) $trait_name:ident
1625 $(#[$fn_meta:meta])*
1626 fn $fn_name:ident()
1627 $(
1628 $(#[$output_meta:meta])*
1629 type Output
1630 )?
1631 } => {
1632 $(#[$trait_meta])*
1633 pub trait $trait_name
1634 where
1635 Self: Sealed
1636 {
1637 $($(#[$output_meta])*)?
1638 type Output;
1639
1640 $(#[$fn_meta])*
1641 fn $fn_name(self) -> (Self::Output, bool);
1642 }
1643 };
1644
1645 {
1646 $(#[$trait_meta:meta])*
1647 trait(unsafe) $trait_name:ident
1648 $(#[$fn_meta:meta])*
1649 fn $fn_name:ident(rhs)
1650 $(
1651 $(#[$output_meta:meta])*
1652 type Output
1653 )?
1654 } => {
1655 $(#[$trait_meta])*
1656 pub trait $trait_name<R>
1657 where
1658 Self: Sealed,
1659 R: Sealed
1660 {
1661 $($(#[$output_meta])*)?
1662 type Output;
1663
1664 $(#[$fn_meta])*
1665 unsafe fn $fn_name(self, rhs: R) -> Self::Output;
1670 }
1671 };
1672
1673 {
1674 $(#[$trait_meta:meta])*
1675 trait(unsafe) $trait_name:ident
1676 $(#[$fn_meta:meta])*
1677 fn $fn_name:ident()
1678 $(
1679 $(#[$output_meta:meta])*
1680 type Output
1681 )?
1682 } => {
1683 $(#[$trait_meta])*
1684 pub trait $trait_name
1685 where
1686 Self: Sealed
1687 {
1688 $($(#[$output_meta])*)?
1689 type Output;
1690
1691 $(#[$fn_meta])*
1692 unsafe fn $fn_name(self) -> Self::Output;
1697 }
1698 };
1699
1700 {
1701 impl
1702 $(
1703 $lhs:ident: $lhs_ty:ident { $($lhs_stuff:tt)* }
1704 )*
1705 } => {
1706 $(
1707 op_trait! {
1708 impl(lhs_stuff)
1709 $lhs $lhs_ty $($lhs_stuff)*
1710 }
1711 )*
1712 };
1713
1714 {
1715 impl(lhs_stuff)
1716 $lhs:ident $lhs_ty:ident
1717 $rhs:ident: $rhs_ty:ident { $($rhs_stuff:tt)* }
1718 $($rest:tt)*
1719 } => {
1720 op_trait! {
1721 impl(rhs_stuff)
1722 $lhs $lhs_ty
1723 $rhs $rhs_ty
1724 $($rhs_stuff)*
1725 }
1726 op_trait! {
1727 impl(lhs_stuff)
1728 $lhs $lhs_ty
1729 $($rest)*
1730 }
1731 };
1732
1733 {
1734 impl(lhs_stuff)
1735 $lhs:ident $lhs_ty:ident
1736 $(#[$meta:meta])*
1737 $op:ident -> $output_ty:ident { $($body:tt)* }
1738 $($rest:tt)*
1739 } => {
1740 op_trait! {
1741 impl(helper_lhs)
1742 $op
1743 $(#[$meta])*
1744 $lhs $lhs_ty
1745 $output_ty
1746 $($body)*
1747 }
1748 op_trait! {
1749 impl(lhs_stuff)
1750 $lhs $lhs_ty
1751 $($rest)*
1752 }
1753 };
1754
1755 {
1756 impl(lhs_stuff)
1757 $lhs:ident $lhs_ty:ident
1758 } => {};
1759
1760 {
1761 impl(rhs_stuff)
1762 $lhs:ident $lhs_ty:ident
1763 $rhs:ident $rhs_ty:ident
1764 $(#[$meta:meta])*
1765 $op:ident -> $output_ty:ident { $($body:tt)* }
1766 $($rest:tt)*
1767 } => {
1768 op_trait! {
1769 impl(helper_rhs)
1770 $op
1771 $(#[$meta])*
1772 $lhs $lhs_ty
1773 $rhs $rhs_ty
1774 $output_ty
1775 $($body)*
1776 }
1777 op_trait! {
1778 impl(rhs_stuff)
1779 $lhs $lhs_ty
1780 $rhs $rhs_ty
1781 $($rest)*
1782 }
1783 };
1784
1785 {
1786 impl(rhs_stuff)
1787 $lhs:ident $lhs_ty:ident
1788 $rhs:ident $rhs_ty:ident
1789 } => {};
1790
1791 {
1792 impl(normal)
1793 $trait_name:ident $fn_name:ident
1794 $(#[$meta:meta])*
1795 $lhs:ident $lhs_ty:ident
1796 $rhs:ident $rhs_ty:ident
1797 $output_ty:ident
1798 $($body:tt)*
1799 } => {
1800 $(#[$meta])*
1801 impl $trait_name<$rhs_ty> for $lhs_ty {
1802 type Output = $output_ty;
1803
1804 #[inline(always)]
1805 fn $fn_name(self, rhs: $rhs_ty) -> $output_ty {
1806 #[inline(always)]
1807 fn inner($lhs: $lhs_ty, $rhs: $rhs_ty) -> $output_ty {
1808 $($body)*
1809 }
1810
1811 inner(self, rhs)
1812 }
1813 }
1814 };
1815
1816 {
1817 impl(normal1)
1818 $trait_name:ident $fn_name:ident
1819 $(#[$meta:meta])*
1820 $lhs:ident $lhs_ty:ident
1821 $output_ty:ident
1822 $($body:tt)*
1823 } => {
1824 $(#[$meta])*
1825 impl $trait_name for $lhs_ty {
1826 type Output = $output_ty;
1827
1828 #[inline(always)]
1829 fn $fn_name(self) -> $output_ty {
1830 #[inline(always)]
1831 fn inner($lhs: $lhs_ty) -> $output_ty {
1832 $($body)*
1833 }
1834
1835 inner(self)
1836 }
1837 }
1838 };
1839
1840 { impl(helper_rhs) add $($stuff:tt)* } => { op_trait! { impl(normal) Add add $($stuff)* } };
1841 { impl(helper_rhs) sub $($stuff:tt)* } => { op_trait! { impl(normal) Sub sub $($stuff)* } };
1842 { impl(helper_rhs) mul $($stuff:tt)* } => { op_trait! { impl(normal) Mul mul $($stuff)* } };
1843 { impl(helper_rhs) div $($stuff:tt)* } => { op_trait! { impl(normal) Div div $($stuff)* } };
1844 { impl(helper_lhs) neg $($stuff:tt)* } => { op_trait! { impl(normal1) Neg neg $($stuff)* } };
1845}
1846
1847op_trait! { trait Add fn add(rhs) }
1848op_trait! { trait Sub fn sub(rhs) }
1849op_trait! { trait Mul fn mul(rhs) }
1850op_trait! { trait Div fn div(rhs) }
1851op_trait! { trait Neg fn neg() }
1852
1853op_trait! { trait(option) AddChecked fn add_checked(rhs) }
1854op_trait! { trait(option) SubChecked fn sub_checked(rhs) }
1855op_trait! { trait(option) MulChecked fn mul_checked(rhs) }
1856op_trait! { trait(option) DivChecked fn div_checked(rhs) }
1857op_trait! { trait(option) NegChecked fn neg_checked() }
1858
1859op_trait! { trait(tuple) AddOverflowing fn add_overflowing(rhs) }
1860op_trait! { trait(tuple) SubOverflowing fn sub_overflowing(rhs) }
1861op_trait! { trait(tuple) MulOverflowing fn mul_overflowing(rhs) }
1862op_trait! { trait(tuple) DivOverflowing fn div_overflowing(rhs) }
1863op_trait! { trait(tuple) NegOverflowing fn neg_overflowing() }
1864
1865op_trait! { trait AddSaturating fn add_saturating(rhs) }
1866op_trait! { trait SubSaturating fn sub_saturating(rhs) }
1867op_trait! { trait MulSaturating fn mul_saturating(rhs) }
1868op_trait! { trait DivSaturating fn div_saturating(rhs) }
1869op_trait! { trait NegSaturating fn neg_saturating() }
1870
1871op_trait! { trait(unsafe) AddUnchecked fn add_unchecked(rhs) }
1875op_trait! { trait(unsafe) SubUnchecked fn sub_unchecked(rhs) }
1876op_trait! { trait(unsafe) MulUnchecked fn mul_unchecked(rhs) }
1877op_trait! { trait(unsafe) DivUnchecked fn div_unchecked(rhs) }
1878op_trait! { trait(unsafe) NegUnchecked fn neg_unchecked() }
1879
1880op_trait! { trait AddWrapping fn add_wrapping(rhs) }
1881op_trait! { trait SubWrapping fn sub_wrapping(rhs) }
1882op_trait! { trait MulWrapping fn mul_wrapping(rhs) }
1883op_trait! { trait DivWrapping fn div_wrapping(rhs) }
1884op_trait! { trait NegWrapping fn neg_wrapping() }
1885
1886op_trait! {
1887 impl
1888
1889 lhs: u8 {
1890 rhs: u8 {
1891 add -> u8 { lhs + rhs }
1892 sub -> u8 { lhs - rhs }
1893 mul -> u8 { lhs * rhs }
1894 div -> u8 { lhs / rhs }
1895 }
1896
1897 rhs: u16 {
1898 add -> u16 { lhs.into_u16() + rhs }
1899 sub -> u16 { lhs.into_u16() - rhs }
1900 mul -> u16 { lhs.into_u16() * rhs }
1901 div -> u16 { lhs.into_u16() / rhs }
1902 }
1903
1904 rhs: u32 {
1905 add -> u32 { lhs.into_u32() + rhs }
1906 sub -> u32 { lhs.into_u32() - rhs }
1907 mul -> u32 { lhs.into_u32() * rhs }
1908 div -> u32 { lhs.into_u32() / rhs }
1909 }
1910
1911 rhs: u64 {
1912 add -> u64 { lhs.into_u64() + rhs }
1913 sub -> u64 { lhs.into_u64() - rhs }
1914 mul -> u64 { lhs.into_u64() * rhs }
1915 div -> u64 { lhs.into_u64() / rhs }
1916 }
1917
1918 rhs: u128 {
1919 add -> u128 { lhs.into_u128() + rhs }
1920 sub -> u128 { lhs.into_u128() - rhs }
1921 mul -> u128 { lhs.into_u128() * rhs }
1922 div -> u128 { lhs.into_u128() / rhs }
1923 }
1924
1925 rhs: usize {
1926 add -> usize { lhs.into_usize() + rhs }
1927 sub -> usize { lhs.into_usize() - rhs }
1928 mul -> usize { lhs.into_usize() * rhs }
1929 div -> usize { lhs.into_usize() / rhs }
1930 }
1931 }
1932
1933 lhs: u16 {}
1934
1935 lhs: u32 {}
1936
1937 lhs: u64 {}
1938
1939 lhs: u128 {}
1940
1941 lhs: usize {}
1942
1943 lhs: i8 {
1944 neg -> i8 { -lhs }
1945 rhs: i8 {
1946 add -> i8 { lhs + rhs }
1947 }
1948 }
1949
1950 lhs: i16 {}
1951
1952 lhs: i32 {}
1953
1954 lhs: i64 {}
1955
1956 lhs: i128 {}
1957
1958 lhs: isize {}
1959
1960 lhs: f32 {}
1961
1962 lhs: f64 {}
1963}
1964
1965mod private {
2163 use super::*;
2164
2165 pub trait Sealed
2167 where
2168 Self: Sized
2169 {}
2170
2171 macro_rules! impl_sealed {
2172 { $($type:ident)* } => {
2173 $(
2174 impl Sealed for $type {}
2175 )*
2176 }
2177 }
2178
2179 impl_sealed! {
2180 u8 u16 u32 u64 u128 usize
2181 i8 i16 i32 i64 i128 isize
2182 f32 f64
2183 bool
2184 }
2185
2186 impl<T> Sealed for &T
2187 where
2188 T: Sealed
2189 {}
2190
2191 impl<T> Sealed for &mut T
2192 where
2193 T: Sealed
2194 {}
2195}