@@ -358,6 +358,22 @@ fn align_offset_zst() {
358
358
}
359
359
}
360
360
361
+ #[ test]
362
+ fn align_offset_zst_const ( ) {
363
+ const {
364
+ // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
365
+ // all, because no amount of elements will align the pointer.
366
+ let mut p = 1 ;
367
+ while p < 1024 {
368
+ assert ! ( ptr:: invalid:: <( ) >( p) . align_offset( p) == 0 ) ;
369
+ if p != 1 {
370
+ assert ! ( ptr:: invalid:: <( ) >( p + 1 ) . align_offset( p) == !0 ) ;
371
+ }
372
+ p = ( p + 1 ) . next_power_of_two ( ) ;
373
+ }
374
+ }
375
+ }
376
+
361
377
#[ test]
362
378
fn align_offset_stride_one ( ) {
363
379
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
@@ -379,6 +395,25 @@ fn align_offset_stride_one() {
379
395
}
380
396
}
381
397
398
+ #[ test]
399
+ fn align_offset_stride_one_const ( ) {
400
+ const {
401
+ // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
402
+ // number of bytes.
403
+ let mut align = 1 ;
404
+ while align < 1024 {
405
+ let mut ptr = 1 ;
406
+ while ptr < 2 * align {
407
+ let expected = ptr % align;
408
+ let offset = if expected == 0 { 0 } else { align - expected } ;
409
+ assert ! ( ptr:: invalid:: <u8 >( ptr) . align_offset( align) == offset) ;
410
+ ptr += 1 ;
411
+ }
412
+ align = ( align + 1 ) . next_power_of_two ( ) ;
413
+ }
414
+ }
415
+ }
416
+
382
417
#[ test]
383
418
fn align_offset_various_strides ( ) {
384
419
unsafe fn test_stride < T > ( ptr : * const T , align : usize ) -> bool {
@@ -455,6 +490,132 @@ fn align_offset_various_strides() {
455
490
assert ! ( !x) ;
456
491
}
457
492
493
+ #[ test]
494
+ fn align_offset_various_strides_const ( ) {
495
+ const unsafe fn test_stride < T > ( ptr : * const T , numptr : usize , align : usize ) {
496
+ let mut expected = usize:: MAX ;
497
+ // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
498
+ let mut el = 0 ;
499
+ while el < align {
500
+ if ( numptr + el * :: std:: mem:: size_of :: < T > ( ) ) % align == 0 {
501
+ expected = el;
502
+ break ;
503
+ }
504
+ el += 1 ;
505
+ }
506
+ let got = ptr. align_offset ( align) ;
507
+ assert ! ( got == expected) ;
508
+ }
509
+
510
+ // For pointers of stride != 1, we verify the algorithm against the naivest possible
511
+ // implementation
512
+ let mut align = 1 ;
513
+ let limit = 1024 ;
514
+ while align < limit {
515
+ for ptr in 1usize ..4 * align {
516
+ unsafe {
517
+ #[ repr( packed) ]
518
+ struct A3 ( u16 , u8 ) ;
519
+ test_stride :: < A3 > ( ptr:: invalid :: < A3 > ( ptr) , ptr, align) ;
520
+
521
+ struct A4 ( u32 ) ;
522
+ test_stride :: < A4 > ( ptr:: invalid :: < A4 > ( ptr) , ptr, align) ;
523
+
524
+ #[ repr( packed) ]
525
+ struct A5 ( u32 , u8 ) ;
526
+ test_stride :: < A5 > ( ptr:: invalid :: < A5 > ( ptr) , ptr, align) ;
527
+
528
+ #[ repr( packed) ]
529
+ struct A6 ( u32 , u16 ) ;
530
+ test_stride :: < A6 > ( ptr:: invalid :: < A6 > ( ptr) , ptr, align) ;
531
+
532
+ #[ repr( packed) ]
533
+ struct A7 ( u32 , u16 , u8 ) ;
534
+ test_stride :: < A7 > ( ptr:: invalid :: < A7 > ( ptr) , ptr, align) ;
535
+
536
+ #[ repr( packed) ]
537
+ struct A8 ( u32 , u32 ) ;
538
+ test_stride :: < A8 > ( ptr:: invalid :: < A8 > ( ptr) , ptr, align) ;
539
+
540
+ #[ repr( packed) ]
541
+ struct A9 ( u32 , u32 , u8 ) ;
542
+ test_stride :: < A9 > ( ptr:: invalid :: < A9 > ( ptr) , ptr, align) ;
543
+
544
+ #[ repr( packed) ]
545
+ struct A10 ( u32 , u32 , u16 ) ;
546
+ test_stride :: < A10 > ( ptr:: invalid :: < A10 > ( ptr) , ptr, align) ;
547
+
548
+ test_stride :: < u32 > ( ptr:: invalid :: < u32 > ( ptr) , ptr, align) ;
549
+ test_stride :: < u128 > ( ptr:: invalid :: < u128 > ( ptr) , ptr, align) ;
550
+ }
551
+ }
552
+ align = ( align + 1 ) . next_power_of_two ( ) ;
553
+ }
554
+ }
555
+
556
+ #[ test]
557
+ fn align_offset_with_provenance_const ( ) {
558
+ const {
559
+ let data = 42 ;
560
+
561
+ let ptr: * const i32 = & data;
562
+ assert ! ( ptr. align_offset( 1 ) == 0 ) ;
563
+ assert ! ( ptr. align_offset( 2 ) == 0 ) ;
564
+ assert ! ( ptr. align_offset( 4 ) == 0 ) ;
565
+ assert ! ( ptr. align_offset( 8 ) == usize :: MAX ) ;
566
+ assert ! ( ptr. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
567
+ assert ! ( ptr. wrapping_byte_add( 1 ) . align_offset( 2 ) == usize :: MAX ) ;
568
+ assert ! ( ptr. wrapping_byte_add( 2 ) . align_offset( 1 ) == 0 ) ;
569
+ assert ! ( ptr. wrapping_byte_add( 2 ) . align_offset( 2 ) == 0 ) ;
570
+ assert ! ( ptr. wrapping_byte_add( 2 ) . align_offset( 4 ) == usize :: MAX ) ;
571
+ assert ! ( ptr. wrapping_byte_add( 3 ) . align_offset( 1 ) == 0 ) ;
572
+ assert ! ( ptr. wrapping_byte_add( 3 ) . align_offset( 2 ) == usize :: MAX ) ;
573
+
574
+ assert ! ( ptr. wrapping_add( 42 ) . align_offset( 4 ) == 0 ) ;
575
+ assert ! ( ptr. wrapping_add( 42 ) . align_offset( 8 ) == usize :: MAX ) ;
576
+
577
+ let ptr1: * const i8 = ptr. cast ( ) ;
578
+ assert ! ( ptr1. align_offset( 1 ) == 0 ) ;
579
+ assert ! ( ptr1. align_offset( 2 ) == 0 ) ;
580
+ assert ! ( ptr1. align_offset( 4 ) == 0 ) ;
581
+ assert ! ( ptr1. align_offset( 8 ) == usize :: MAX ) ;
582
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
583
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 2 ) == 1 ) ;
584
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 4 ) == 3 ) ;
585
+ assert ! ( ptr1. wrapping_byte_add( 1 ) . align_offset( 8 ) == usize :: MAX ) ;
586
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 1 ) == 0 ) ;
587
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 2 ) == 0 ) ;
588
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 4 ) == 2 ) ;
589
+ assert ! ( ptr1. wrapping_byte_add( 2 ) . align_offset( 8 ) == usize :: MAX ) ;
590
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 1 ) == 0 ) ;
591
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 2 ) == 1 ) ;
592
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 4 ) == 1 ) ;
593
+ assert ! ( ptr1. wrapping_byte_add( 3 ) . align_offset( 8 ) == usize :: MAX ) ;
594
+
595
+ let ptr2: * const i16 = ptr. cast ( ) ;
596
+ assert ! ( ptr2. align_offset( 1 ) == 0 ) ;
597
+ assert ! ( ptr2. align_offset( 2 ) == 0 ) ;
598
+ assert ! ( ptr2. align_offset( 4 ) == 0 ) ;
599
+ assert ! ( ptr2. align_offset( 8 ) == usize :: MAX ) ;
600
+ assert ! ( ptr2. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
601
+ assert ! ( ptr2. wrapping_byte_add( 1 ) . align_offset( 2 ) == usize :: MAX ) ;
602
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 1 ) == 0 ) ;
603
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 2 ) == 0 ) ;
604
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 4 ) == 1 ) ;
605
+ assert ! ( ptr2. wrapping_byte_add( 2 ) . align_offset( 8 ) == usize :: MAX ) ;
606
+ assert ! ( ptr2. wrapping_byte_add( 3 ) . align_offset( 1 ) == 0 ) ;
607
+ assert ! ( ptr2. wrapping_byte_add( 3 ) . align_offset( 2 ) == usize :: MAX ) ;
608
+
609
+ let ptr3: * const i64 = ptr. cast ( ) ;
610
+ assert ! ( ptr3. align_offset( 1 ) == 0 ) ;
611
+ assert ! ( ptr3. align_offset( 2 ) == 0 ) ;
612
+ assert ! ( ptr3. align_offset( 4 ) == 0 ) ;
613
+ assert ! ( ptr3. align_offset( 8 ) == usize :: MAX ) ;
614
+ assert ! ( ptr3. wrapping_byte_add( 1 ) . align_offset( 1 ) == 0 ) ;
615
+ assert ! ( ptr3. wrapping_byte_add( 1 ) . align_offset( 2 ) == usize :: MAX ) ;
616
+ }
617
+ }
618
+
458
619
#[ test]
459
620
fn offset_from ( ) {
460
621
let mut a = [ 0 ; 5 ] ;
0 commit comments