@@ -700,6 +700,114 @@ impl<T: ?Sized> *const T {
700700 }
701701 }
702702
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+
703811 /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
704812 ///
705813 /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
@@ -1347,6 +1455,105 @@ impl<T: ?Sized> *mut T {
13471455 }
13481456 }
13491457
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+
13501557 /// Computes the byte offset that needs to be applied in order to
13511558 /// make the pointer aligned to `align`.
13521559 /// If it is not possible to align the pointer, the implementation returns
0 commit comments