5
5
use num_traits:: cast:: * ;
6
6
use num_traits:: Bounded ;
7
7
8
+ use core:: num:: {
9
+ NonZeroI128 , NonZeroI16 , NonZeroI32 , NonZeroI64 , NonZeroI8 , NonZeroIsize , NonZeroU128 ,
10
+ NonZeroU16 , NonZeroU32 , NonZeroU64 , NonZeroU8 , NonZeroUsize ,
11
+ } ;
8
12
use core:: { f32, f64} ;
9
13
use core:: { i128, i16, i32, i64, i8, isize} ;
10
14
use core:: { u128, u16, u32, u64, u8, usize} ;
@@ -101,17 +105,50 @@ fn cast_to_int_checks_overflow() {
101
105
assert_eq ! ( None , cast:: <f64 , i32 >( big_f) ) ;
102
106
assert_eq ! ( None , cast:: <f64 , i64 >( big_f) ) ;
103
107
108
+ assert_eq ! ( None , cast:: <f64 , NonZeroIsize >( big_f) ) ;
109
+ assert_eq ! ( None , cast:: <f64 , NonZeroI8 >( big_f) ) ;
110
+ assert_eq ! ( None , cast:: <f64 , NonZeroI16 >( big_f) ) ;
111
+ assert_eq ! ( None , cast:: <f64 , NonZeroI32 >( big_f) ) ;
112
+ assert_eq ! ( None , cast:: <f64 , NonZeroI64 >( big_f) ) ;
113
+
104
114
assert_eq ! ( Some ( normal_f as isize ) , cast:: <f64 , isize >( normal_f) ) ;
105
115
assert_eq ! ( Some ( normal_f as i8 ) , cast:: <f64 , i8 >( normal_f) ) ;
106
116
assert_eq ! ( Some ( normal_f as i16 ) , cast:: <f64 , i16 >( normal_f) ) ;
107
117
assert_eq ! ( Some ( normal_f as i32 ) , cast:: <f64 , i32 >( normal_f) ) ;
108
118
assert_eq ! ( Some ( normal_f as i64 ) , cast:: <f64 , i64 >( normal_f) ) ;
109
119
120
+ assert_eq ! (
121
+ NonZeroIsize :: new( normal_f as isize ) ,
122
+ cast:: <f64 , NonZeroIsize >( normal_f)
123
+ ) ;
124
+ assert_eq ! (
125
+ NonZeroI8 :: new( normal_f as i8 ) ,
126
+ cast:: <f64 , NonZeroI8 >( normal_f)
127
+ ) ;
128
+ assert_eq ! (
129
+ NonZeroI16 :: new( normal_f as i16 ) ,
130
+ cast:: <f64 , NonZeroI16 >( normal_f)
131
+ ) ;
132
+ assert_eq ! (
133
+ NonZeroI32 :: new( normal_f as i32 ) ,
134
+ cast:: <f64 , NonZeroI32 >( normal_f)
135
+ ) ;
136
+ assert_eq ! (
137
+ NonZeroI64 :: new( normal_f as i64 ) ,
138
+ cast:: <f64 , NonZeroI64 >( normal_f)
139
+ ) ;
140
+
110
141
assert_eq ! ( None , cast:: <f64 , isize >( small_f) ) ;
111
142
assert_eq ! ( None , cast:: <f64 , i8 >( small_f) ) ;
112
143
assert_eq ! ( None , cast:: <f64 , i16 >( small_f) ) ;
113
144
assert_eq ! ( None , cast:: <f64 , i32 >( small_f) ) ;
114
145
assert_eq ! ( None , cast:: <f64 , i64 >( small_f) ) ;
146
+
147
+ assert_eq ! ( None , cast:: <f64 , NonZeroIsize >( small_f) ) ;
148
+ assert_eq ! ( None , cast:: <f64 , NonZeroI8 >( small_f) ) ;
149
+ assert_eq ! ( None , cast:: <f64 , NonZeroI16 >( small_f) ) ;
150
+ assert_eq ! ( None , cast:: <f64 , NonZeroI32 >( small_f) ) ;
151
+ assert_eq ! ( None , cast:: <f64 , NonZeroI64 >( small_f) ) ;
115
152
}
116
153
117
154
#[ test]
@@ -125,17 +162,50 @@ fn cast_to_unsigned_int_checks_overflow() {
125
162
assert_eq ! ( None , cast:: <f64 , u32 >( big_f) ) ;
126
163
assert_eq ! ( None , cast:: <f64 , u64 >( big_f) ) ;
127
164
165
+ assert_eq ! ( None , cast:: <f64 , NonZeroUsize >( big_f) ) ;
166
+ assert_eq ! ( None , cast:: <f64 , NonZeroU8 >( big_f) ) ;
167
+ assert_eq ! ( None , cast:: <f64 , NonZeroU16 >( big_f) ) ;
168
+ assert_eq ! ( None , cast:: <f64 , NonZeroU32 >( big_f) ) ;
169
+ assert_eq ! ( None , cast:: <f64 , NonZeroU64 >( big_f) ) ;
170
+
128
171
assert_eq ! ( Some ( normal_f as usize ) , cast:: <f64 , usize >( normal_f) ) ;
129
172
assert_eq ! ( Some ( normal_f as u8 ) , cast:: <f64 , u8 >( normal_f) ) ;
130
173
assert_eq ! ( Some ( normal_f as u16 ) , cast:: <f64 , u16 >( normal_f) ) ;
131
174
assert_eq ! ( Some ( normal_f as u32 ) , cast:: <f64 , u32 >( normal_f) ) ;
132
175
assert_eq ! ( Some ( normal_f as u64 ) , cast:: <f64 , u64 >( normal_f) ) ;
133
176
177
+ assert_eq ! (
178
+ NonZeroUsize :: new( normal_f as usize ) ,
179
+ cast:: <f64 , NonZeroUsize >( normal_f)
180
+ ) ;
181
+ assert_eq ! (
182
+ NonZeroU8 :: new( normal_f as u8 ) ,
183
+ cast:: <f64 , NonZeroU8 >( normal_f)
184
+ ) ;
185
+ assert_eq ! (
186
+ NonZeroU16 :: new( normal_f as u16 ) ,
187
+ cast:: <f64 , NonZeroU16 >( normal_f)
188
+ ) ;
189
+ assert_eq ! (
190
+ NonZeroU32 :: new( normal_f as u32 ) ,
191
+ cast:: <f64 , NonZeroU32 >( normal_f)
192
+ ) ;
193
+ assert_eq ! (
194
+ NonZeroU64 :: new( normal_f as u64 ) ,
195
+ cast:: <f64 , NonZeroU64 >( normal_f)
196
+ ) ;
197
+
134
198
assert_eq ! ( None , cast:: <f64 , usize >( small_f) ) ;
135
199
assert_eq ! ( None , cast:: <f64 , u8 >( small_f) ) ;
136
200
assert_eq ! ( None , cast:: <f64 , u16 >( small_f) ) ;
137
201
assert_eq ! ( None , cast:: <f64 , u32 >( small_f) ) ;
138
202
assert_eq ! ( None , cast:: <f64 , u64 >( small_f) ) ;
203
+
204
+ assert_eq ! ( None , cast:: <f64 , NonZeroUsize >( small_f) ) ;
205
+ assert_eq ! ( None , cast:: <f64 , NonZeroU8 >( small_f) ) ;
206
+ assert_eq ! ( None , cast:: <f64 , NonZeroU16 >( small_f) ) ;
207
+ assert_eq ! ( None , cast:: <f64 , NonZeroU32 >( small_f) ) ;
208
+ assert_eq ! ( None , cast:: <f64 , NonZeroU64 >( small_f) ) ;
139
209
}
140
210
141
211
#[ test]
@@ -146,11 +216,26 @@ fn cast_to_i128_checks_overflow() {
146
216
assert_eq ! ( None , cast:: <f64 , i128 >( big_f) ) ;
147
217
assert_eq ! ( None , cast:: <f64 , u128 >( big_f) ) ;
148
218
219
+ assert_eq ! ( None , cast:: <f64 , NonZeroI128 >( big_f) ) ;
220
+ assert_eq ! ( None , cast:: <f64 , NonZeroU128 >( big_f) ) ;
221
+
149
222
assert_eq ! ( Some ( normal_f as i128 ) , cast:: <f64 , i128 >( normal_f) ) ;
150
223
assert_eq ! ( Some ( normal_f as u128 ) , cast:: <f64 , u128 >( normal_f) ) ;
151
224
225
+ assert_eq ! (
226
+ NonZeroI128 :: new( normal_f as i128 ) ,
227
+ cast:: <f64 , NonZeroI128 >( normal_f)
228
+ ) ;
229
+ assert_eq ! (
230
+ NonZeroU128 :: new( normal_f as u128 ) ,
231
+ cast:: <f64 , NonZeroU128 >( normal_f)
232
+ ) ;
233
+
152
234
assert_eq ! ( None , cast:: <f64 , i128 >( small_f) ) ;
153
235
assert_eq ! ( None , cast:: <f64 , u128 >( small_f) ) ;
236
+
237
+ assert_eq ! ( None , cast:: <f64 , NonZeroI128 >( small_f) ) ;
238
+ assert_eq ! ( None , cast:: <f64 , NonZeroU128 >( small_f) ) ;
154
239
}
155
240
156
241
#[ cfg( feature = "std" ) ]
@@ -310,6 +395,152 @@ fn cast_int_to_128_edge_cases() {
310
395
test_edge ! ( usize u8 u16 u32 u64 u128 ) ;
311
396
}
312
397
398
+ macro_rules! nonzero_to_int_test_edge {
399
+ ( $f: ident -> { $( $t: ident) + } with $BigS: ident $BigU: ident ) => { $( {
400
+ #[ allow( arithmetic_overflow) ] // https://github.com/rust-lang/rust/issues/109731
401
+ fn test_edge( ) {
402
+ dbg!( "testing cast edge cases for {} -> {}" , stringify!( $f) , stringify!( $t) ) ;
403
+
404
+
405
+ let from_min = <$f as Bounded >:: min_value( ) ;
406
+ match ( from_min. get( ) as $BigS) . cmp( & ( $t:: MIN as $BigS) ) {
407
+ Greater => {
408
+ assert_eq!( Some ( from_min. get( ) as $t) , cast:: <$f, $t>( from_min) ) ;
409
+ }
410
+ Equal => {
411
+ assert_eq!( Some ( $t:: MIN ) , cast:: <$f, $t>( from_min) ) ;
412
+ }
413
+ Less => {
414
+ if $t:: MIN != 0 {
415
+ let min = $f:: new( $t:: MIN . as_( ) ) . unwrap( ) ;
416
+ assert_eq!( Some ( $t:: MIN ) , cast:: <$f, $t>( min) ) ;
417
+ assert_eq!( None , cast:: <$f, $t>( $f:: new( min. get( ) - 1 ) . unwrap( ) ) ) ;
418
+ }
419
+ }
420
+ }
421
+
422
+ let from_max = <$f as Bounded >:: max_value( ) ;
423
+ match ( from_max. get( ) as $BigU) . cmp( & ( $t:: MAX as $BigU) ) {
424
+ Greater => {
425
+ let max = $f:: new( $t:: MAX . as_( ) ) . unwrap( ) ;
426
+ assert_eq!( Some ( $t:: MAX ) , cast:: <$f, $t>( max) ) ;
427
+ assert_eq!( None , cast:: <$f, $t>( $f:: new( max. get( ) + 1 ) . unwrap( ) ) ) ;
428
+ }
429
+ Equal => {
430
+ assert_eq!( Some ( $t:: MAX ) , cast:: <$f, $t>( from_max) ) ;
431
+ }
432
+ Less => {
433
+ assert_eq!( Some ( from_max. get( ) as $t) , cast:: <$f, $t>( from_max) ) ;
434
+ }
435
+ }
436
+ }
437
+ test_edge( ) ;
438
+ } ) +}
439
+ }
440
+
441
+ #[ test]
442
+ fn cast_nonzero_to_int_edge_cases ( ) {
443
+ use core:: cmp:: Ordering :: * ;
444
+
445
+ macro_rules! test_edge {
446
+ ( $( $from: ident ) +) => { $( {
447
+ nonzero_to_int_test_edge!( $from -> { isize i8 i16 i32 i64 } with i64 u64 ) ;
448
+ nonzero_to_int_test_edge!( $from -> { usize u8 u16 u32 u64 } with i64 u64 ) ;
449
+ } ) +}
450
+ }
451
+
452
+ test_edge ! ( NonZeroIsize NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 ) ;
453
+ test_edge ! ( NonZeroUsize NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 ) ;
454
+ }
455
+
456
+ #[ test]
457
+ fn cast_nonzero_to_128_edge_cases ( ) {
458
+ use core:: cmp:: Ordering :: * ;
459
+
460
+ macro_rules! test_edge {
461
+ ( $( $t: ident ) +) => {
462
+ $(
463
+ nonzero_to_int_test_edge!( $t -> { i128 u128 } with i128 u128 ) ;
464
+ ) +
465
+ }
466
+ }
467
+
468
+ test_edge ! ( NonZeroIsize NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 ) ;
469
+ test_edge ! ( NonZeroUsize NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 ) ;
470
+ }
471
+
472
+ macro_rules! int_to_nonzero_test_edge {
473
+ ( $f: ident -> { $( $t: ident) + } with $BigS: ident $BigU: ident ) => { $( {
474
+ #[ allow( arithmetic_overflow) ] // https://github.com/rust-lang/rust/issues/109731
475
+ fn test_edge( ) {
476
+ dbg!( "testing cast edge cases for {} -> {}" , stringify!( $f) , stringify!( $t) ) ;
477
+
478
+ let target_min = <$t as Bounded >:: min_value( ) ;
479
+ match ( $f:: MIN as $BigS) . cmp( & ( target_min. get( ) as $BigS) ) {
480
+ Greater => {
481
+ assert_eq!( $t:: new( $f:: MIN . as_( ) ) , cast:: <$f, $t>( $f:: MIN ) ) ;
482
+ }
483
+ Equal => {
484
+ assert_eq!( Some ( target_min) , cast:: <$f, $t>( $f:: MIN ) ) ;
485
+ }
486
+ Less => {
487
+ let min = target_min. get( ) as $f;
488
+ assert_eq!( Some ( target_min) , cast:: <$f, $t>( min) ) ;
489
+ assert_eq!( None , cast:: <$f, $t>( min - 1 ) ) ;
490
+ }
491
+ }
492
+
493
+ let target_max = <$t as Bounded >:: max_value( ) ;
494
+ match ( $f:: MAX as $BigU) . cmp( & ( $t:: max_value( ) . get( ) as $BigU) ) {
495
+ Greater => {
496
+ let max = target_max. get( ) as $f;
497
+ assert_eq!( Some ( target_max) , cast:: <$f, $t>( max) ) ;
498
+ assert_eq!( None , cast:: <$f, $t>( max + 1 ) ) ;
499
+ }
500
+ Equal => {
501
+ assert_eq!( Some ( target_max) , cast:: <$f, $t>( $f:: MAX ) ) ;
502
+ }
503
+ Less => {
504
+ assert_eq!( $t:: new( $f:: MAX . as_( ) ) , cast:: <$f, $t>( $f:: MAX ) ) ;
505
+ }
506
+ }
507
+ }
508
+ test_edge( ) ;
509
+ } ) +}
510
+ }
511
+
512
+ #[ test]
513
+ fn cast_int_to_nonzero_edge_cases ( ) {
514
+ use core:: cmp:: Ordering :: * ;
515
+
516
+ macro_rules! test_edge {
517
+ ( $( $from: ident ) +) => { $( {
518
+ int_to_nonzero_test_edge!( $from -> { NonZeroIsize NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 } with i64 u64 ) ;
519
+ int_to_nonzero_test_edge!( $from -> { NonZeroUsize NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 } with i64 u64 ) ;
520
+ } ) +}
521
+ }
522
+
523
+ test_edge ! ( isize i8 i16 i32 i64 ) ;
524
+ test_edge ! ( usize u8 u16 u32 u64 ) ;
525
+ }
526
+
527
+ #[ test]
528
+ fn cast_128_to_nonzero_edge_cases ( ) {
529
+ use core:: cmp:: Ordering :: * ;
530
+
531
+ macro_rules! test_edge {
532
+ ( $( $t: ident ) +) => {
533
+ $(
534
+ int_to_nonzero_test_edge!( $t -> { NonZeroIsize NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 } with i128 u128 ) ;
535
+ int_to_nonzero_test_edge!( $t -> { NonZeroUsize NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 } with i128 u128 ) ;
536
+ ) +
537
+ }
538
+ }
539
+
540
+ test_edge ! ( isize i8 i16 i32 i64 i128 ) ;
541
+ test_edge ! ( usize u8 u16 u32 u64 u128 ) ;
542
+ }
543
+
313
544
#[ test]
314
545
fn newtype_from_primitive ( ) {
315
546
#[ derive( PartialEq , Debug ) ]
0 commit comments