@@ -700,6 +700,114 @@ impl<T: ?Sized> *const T {
700
700
}
701
701
}
702
702
703
+ /// Calculates the distance between two pointers. The returned value is in
704
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
705
+ ///
706
+ /// This function is the inverse of [`offset`].
707
+ ///
708
+ /// [`offset`]: #method.offset
709
+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from
710
+ ///
711
+ /// # Safety
712
+ ///
713
+ /// If any of the following conditions are violated, the result is Undefined
714
+ /// Behavior:
715
+ ///
716
+ /// * Both the starting and other pointer must be either in bounds or one
717
+ /// byte past the end of the same allocated object.
718
+ ///
719
+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
720
+ ///
721
+ /// * The distance between the pointers, in bytes, must be an exact multiple
722
+ /// of the size of `T` and `T` must not be a Zero-Sized Type ("ZST").
723
+ ///
724
+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
725
+ ///
726
+ /// The compiler and standard library generally try to ensure allocations
727
+ /// never reach a size where an offset is a concern. For instance, `Vec`
728
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
729
+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
730
+ ///
731
+ /// Most platforms fundamentally can't even construct such an allocation.
732
+ /// For instance, no known 64-bit platform can ever serve a request
733
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
734
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
735
+ /// more than `isize::MAX` bytes with things like Physical Address
736
+ /// Extension. As such, memory acquired directly from allocators or memory
737
+ /// mapped files *may* be too large to handle with this function.
738
+ ///
739
+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
740
+ /// difficult to satisfy. The only advantage of this method is that it
741
+ /// enables more aggressive compiler optimizations.
742
+ ///
743
+ /// # Examples
744
+ ///
745
+ /// Basic usage:
746
+ ///
747
+ /// ```
748
+ /// #![feature(ptr_offset_from)]
749
+ ///
750
+ /// let a = [0; 5];
751
+ /// let ptr1: *const i32 = &a[1];
752
+ /// let ptr2: *const i32 = &a[3];
753
+ /// unsafe {
754
+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
755
+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
756
+ /// assert_eq!(ptr1.offset(2), ptr2);
757
+ /// assert_eq!(ptr2.offset(-2), ptr1);
758
+ /// }
759
+ /// ```
760
+ #[ unstable( feature = "ptr_offset_from" , issue = "41079" ) ]
761
+ #[ inline]
762
+ pub unsafe fn offset_from ( self , other : * const T ) -> isize where T : Sized {
763
+ let pointee_size = mem:: size_of :: < T > ( ) ;
764
+ assert ! ( 0 < pointee_size && pointee_size <= isize :: max_value( ) as usize ) ;
765
+
766
+ // FIXME: can this be nuw/nsw?
767
+ let d = isize:: wrapping_sub ( self as _ , other as _ ) ;
768
+ intrinsics:: exact_div ( d, pointee_size as _ )
769
+ }
770
+
771
+ /// Calculates the distance between two pointers. The returned value is in
772
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
773
+ ///
774
+ /// If the address different between the two pointers is not a multiple of
775
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
776
+ /// zero.
777
+ ///
778
+ /// # Panics
779
+ ///
780
+ /// This function panics if `T` is a zero-sized typed.
781
+ ///
782
+ /// # Examples
783
+ ///
784
+ /// Basic usage:
785
+ ///
786
+ /// ```
787
+ /// #![feature(ptr_wrapping_offset_from)]
788
+ ///
789
+ /// let a = [0; 5];
790
+ /// let ptr1: *const i32 = &a[1];
791
+ /// let ptr2: *const i32 = &a[3];
792
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
793
+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
794
+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
795
+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
796
+ ///
797
+ /// let ptr1: *const i32 = 3 as _;
798
+ /// let ptr2: *const i32 = 13 as _;
799
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
800
+ /// ```
801
+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "41079" ) ]
802
+ #[ inline]
803
+ pub fn wrapping_offset_from ( self , other : * const T ) -> isize where T : Sized {
804
+ let pointee_size = mem:: size_of :: < T > ( ) ;
805
+ assert ! ( 0 < pointee_size && pointee_size <= isize :: max_value( ) as usize ) ;
806
+
807
+ let d = isize:: wrapping_sub ( self as _ , other as _ ) ;
808
+ d. wrapping_div ( pointee_size as _ )
809
+ }
810
+
703
811
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
704
812
///
705
813
/// `count` is in units of T; e.g. a `count` of 3 represents a pointer
@@ -1347,6 +1455,105 @@ impl<T: ?Sized> *mut T {
1347
1455
}
1348
1456
}
1349
1457
1458
+ /// Calculates the distance between two pointers. The returned value is in
1459
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
1460
+ ///
1461
+ /// This function is the inverse of [`offset`].
1462
+ ///
1463
+ /// [`offset`]: #method.offset-1
1464
+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
1465
+ ///
1466
+ /// # Safety
1467
+ ///
1468
+ /// If any of the following conditions are violated, the result is Undefined
1469
+ /// Behavior:
1470
+ ///
1471
+ /// * Both the starting and other pointer must be either in bounds or one
1472
+ /// byte past the end of the same allocated object.
1473
+ ///
1474
+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
1475
+ ///
1476
+ /// * The distance between the pointers, in bytes, must be an exact multiple
1477
+ /// of the size of `T` and `T` must not be a Zero-Sized Type ("ZST").
1478
+ ///
1479
+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
1480
+ ///
1481
+ /// The compiler and standard library generally try to ensure allocations
1482
+ /// never reach a size where an offset is a concern. For instance, `Vec`
1483
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
1484
+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
1485
+ ///
1486
+ /// Most platforms fundamentally can't even construct such an allocation.
1487
+ /// For instance, no known 64-bit platform can ever serve a request
1488
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
1489
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
1490
+ /// more than `isize::MAX` bytes with things like Physical Address
1491
+ /// Extension. As such, memory acquired directly from allocators or memory
1492
+ /// mapped files *may* be too large to handle with this function.
1493
+ ///
1494
+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
1495
+ /// difficult to satisfy. The only advantage of this method is that it
1496
+ /// enables more aggressive compiler optimizations.
1497
+ ///
1498
+ /// # Examples
1499
+ ///
1500
+ /// Basic usage:
1501
+ ///
1502
+ /// ```
1503
+ /// #![feature(ptr_offset_from)]
1504
+ ///
1505
+ /// let a = [0; 5];
1506
+ /// let ptr1: *mut i32 = &mut a[1];
1507
+ /// let ptr2: *mut i32 = &mut a[3];
1508
+ /// unsafe {
1509
+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
1510
+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
1511
+ /// assert_eq!(ptr1.offset(2), ptr2);
1512
+ /// assert_eq!(ptr2.offset(-2), ptr1);
1513
+ /// }
1514
+ /// ```
1515
+ #[ unstable( feature = "ptr_offset_from" , issue = "41079" ) ]
1516
+ #[ inline]
1517
+ pub unsafe fn offset_from ( self , other : * const T ) -> isize where T : Sized {
1518
+ ( self as * const T ) . offset_from ( other)
1519
+ }
1520
+
1521
+ /// Calculates the distance between two pointers. The returned value is in
1522
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
1523
+ ///
1524
+ /// If the address different between the two pointers is not a multiple of
1525
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
1526
+ /// zero.
1527
+ ///
1528
+ /// # Panics
1529
+ ///
1530
+ /// This function panics if `T` is a zero-sized typed.
1531
+ ///
1532
+ /// # Examples
1533
+ ///
1534
+ /// Basic usage:
1535
+ ///
1536
+ /// ```
1537
+ /// #![feature(ptr_wrapping_offset_from)]
1538
+ ///
1539
+ /// let a = [0; 5];
1540
+ /// let ptr1: *mut i32 = &mut a[1];
1541
+ /// let ptr2: *mut i32 = &mut a[3];
1542
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
1543
+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
1544
+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
1545
+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
1546
+ ///
1547
+ /// let ptr1: *mut i32 = 3 as _;
1548
+ /// let ptr2: *mut i32 = 13 as _;
1549
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
1550
+ /// ```
1551
+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "41079" ) ]
1552
+ #[ inline]
1553
+ pub fn wrapping_offset_from ( self , other : * const T ) -> isize where T : Sized {
1554
+ ( self as * const T ) . wrapping_offset_from ( other)
1555
+ }
1556
+
1350
1557
/// Computes the byte offset that needs to be applied in order to
1351
1558
/// make the pointer aligned to `align`.
1352
1559
/// If it is not possible to align the pointer, the implementation returns
0 commit comments