@@ -669,7 +669,7 @@ impl<T: ?Sized> *const T {
669
669
/// `mem::size_of::<T>()` then the result of the division is rounded towards
670
670
/// zero.
671
671
///
672
- /// This function returns `None` if `T` is a zero-sized typed .
672
+ /// This function returns `None` if `T` is a zero-sized type .
673
673
///
674
674
/// # Examples
675
675
///
@@ -700,6 +700,124 @@ 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`.
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
+ /// # Panics
744
+ ///
745
+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
746
+ ///
747
+ /// # Examples
748
+ ///
749
+ /// Basic usage:
750
+ ///
751
+ /// ```
752
+ /// #![feature(ptr_offset_from)]
753
+ ///
754
+ /// let a = [0; 5];
755
+ /// let ptr1: *const i32 = &a[1];
756
+ /// let ptr2: *const i32 = &a[3];
757
+ /// unsafe {
758
+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
759
+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
760
+ /// assert_eq!(ptr1.offset(2), ptr2);
761
+ /// assert_eq!(ptr2.offset(-2), ptr1);
762
+ /// }
763
+ /// ```
764
+ #[ unstable( feature = "ptr_offset_from" , issue = "41079" ) ]
765
+ #[ inline]
766
+ pub unsafe fn offset_from ( self , origin : * const T ) -> isize where T : Sized {
767
+ let pointee_size = mem:: size_of :: < T > ( ) ;
768
+ assert ! ( 0 < pointee_size && pointee_size <= isize :: max_value( ) as usize ) ;
769
+
770
+ // This is the same sequence that Clang emits for pointer subtraction.
771
+ // It can be neither `nsw` nor `nuw` because the input is treated as
772
+ // unsigned but then the output is treated as signed, so neither works.
773
+ let d = isize:: wrapping_sub ( self as _ , origin as _ ) ;
774
+ intrinsics:: exact_div ( d, pointee_size as _ )
775
+ }
776
+
777
+ /// Calculates the distance between two pointers. The returned value is in
778
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
779
+ ///
780
+ /// If the address different between the two pointers is not a multiple of
781
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
782
+ /// zero.
783
+ ///
784
+ /// Though this method is safe for any two pointers, note that its result
785
+ /// will be mostly useless if the two pointers aren't into the same allocated
786
+ /// object, for example if they point to two different local variables.
787
+ ///
788
+ /// # Panics
789
+ ///
790
+ /// This function panics if `T` is a zero-sized type.
791
+ ///
792
+ /// # Examples
793
+ ///
794
+ /// Basic usage:
795
+ ///
796
+ /// ```
797
+ /// #![feature(ptr_wrapping_offset_from)]
798
+ ///
799
+ /// let a = [0; 5];
800
+ /// let ptr1: *const i32 = &a[1];
801
+ /// let ptr2: *const i32 = &a[3];
802
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
803
+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
804
+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
805
+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
806
+ ///
807
+ /// let ptr1: *const i32 = 3 as _;
808
+ /// let ptr2: *const i32 = 13 as _;
809
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
810
+ /// ```
811
+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "41079" ) ]
812
+ #[ inline]
813
+ pub fn wrapping_offset_from ( self , origin : * const T ) -> isize where T : Sized {
814
+ let pointee_size = mem:: size_of :: < T > ( ) ;
815
+ assert ! ( 0 < pointee_size && pointee_size <= isize :: max_value( ) as usize ) ;
816
+
817
+ let d = isize:: wrapping_sub ( self as _ , origin as _ ) ;
818
+ d. wrapping_div ( pointee_size as _ )
819
+ }
820
+
703
821
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
704
822
///
705
823
/// `count` is in units of T; e.g. a `count` of 3 represents a pointer
@@ -1316,7 +1434,7 @@ impl<T: ?Sized> *mut T {
1316
1434
/// `mem::size_of::<T>()` then the result of the division is rounded towards
1317
1435
/// zero.
1318
1436
///
1319
- /// This function returns `None` if `T` is a zero-sized typed .
1437
+ /// This function returns `None` if `T` is a zero-sized type .
1320
1438
///
1321
1439
/// # Examples
1322
1440
///
@@ -1347,6 +1465,113 @@ impl<T: ?Sized> *mut T {
1347
1465
}
1348
1466
}
1349
1467
1468
+ /// Calculates the distance between two pointers. The returned value is in
1469
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
1470
+ ///
1471
+ /// This function is the inverse of [`offset`].
1472
+ ///
1473
+ /// [`offset`]: #method.offset-1
1474
+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
1475
+ ///
1476
+ /// # Safety
1477
+ ///
1478
+ /// If any of the following conditions are violated, the result is Undefined
1479
+ /// Behavior:
1480
+ ///
1481
+ /// * Both the starting and other pointer must be either in bounds or one
1482
+ /// byte past the end of the same allocated object.
1483
+ ///
1484
+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
1485
+ ///
1486
+ /// * The distance between the pointers, in bytes, must be an exact multiple
1487
+ /// of the size of `T`.
1488
+ ///
1489
+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
1490
+ ///
1491
+ /// The compiler and standard library generally try to ensure allocations
1492
+ /// never reach a size where an offset is a concern. For instance, `Vec`
1493
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
1494
+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
1495
+ ///
1496
+ /// Most platforms fundamentally can't even construct such an allocation.
1497
+ /// For instance, no known 64-bit platform can ever serve a request
1498
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
1499
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
1500
+ /// more than `isize::MAX` bytes with things like Physical Address
1501
+ /// Extension. As such, memory acquired directly from allocators or memory
1502
+ /// mapped files *may* be too large to handle with this function.
1503
+ ///
1504
+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
1505
+ /// difficult to satisfy. The only advantage of this method is that it
1506
+ /// enables more aggressive compiler optimizations.
1507
+ ///
1508
+ /// # Panics
1509
+ ///
1510
+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
1511
+ ///
1512
+ /// # Examples
1513
+ ///
1514
+ /// Basic usage:
1515
+ ///
1516
+ /// ```
1517
+ /// #![feature(ptr_offset_from)]
1518
+ ///
1519
+ /// let mut a = [0; 5];
1520
+ /// let ptr1: *mut i32 = &mut a[1];
1521
+ /// let ptr2: *mut i32 = &mut a[3];
1522
+ /// unsafe {
1523
+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
1524
+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
1525
+ /// assert_eq!(ptr1.offset(2), ptr2);
1526
+ /// assert_eq!(ptr2.offset(-2), ptr1);
1527
+ /// }
1528
+ /// ```
1529
+ #[ unstable( feature = "ptr_offset_from" , issue = "41079" ) ]
1530
+ #[ inline]
1531
+ pub unsafe fn offset_from ( self , origin : * const T ) -> isize where T : Sized {
1532
+ ( self as * const T ) . offset_from ( origin)
1533
+ }
1534
+
1535
+ /// Calculates the distance between two pointers. The returned value is in
1536
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
1537
+ ///
1538
+ /// If the address different between the two pointers is not a multiple of
1539
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
1540
+ /// zero.
1541
+ ///
1542
+ /// Though this method is safe for any two pointers, note that its result
1543
+ /// will be mostly useless if the two pointers aren't into the same allocated
1544
+ /// object, for example if they point to two different local variables.
1545
+ ///
1546
+ /// # Panics
1547
+ ///
1548
+ /// This function panics if `T` is a zero-sized type.
1549
+ ///
1550
+ /// # Examples
1551
+ ///
1552
+ /// Basic usage:
1553
+ ///
1554
+ /// ```
1555
+ /// #![feature(ptr_wrapping_offset_from)]
1556
+ ///
1557
+ /// let mut a = [0; 5];
1558
+ /// let ptr1: *mut i32 = &mut a[1];
1559
+ /// let ptr2: *mut i32 = &mut a[3];
1560
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
1561
+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
1562
+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
1563
+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
1564
+ ///
1565
+ /// let ptr1: *mut i32 = 3 as _;
1566
+ /// let ptr2: *mut i32 = 13 as _;
1567
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
1568
+ /// ```
1569
+ #[ unstable( feature = "ptr_wrapping_offset_from" , issue = "41079" ) ]
1570
+ #[ inline]
1571
+ pub fn wrapping_offset_from ( self , origin : * const T ) -> isize where T : Sized {
1572
+ ( self as * const T ) . wrapping_offset_from ( origin)
1573
+ }
1574
+
1350
1575
/// Computes the byte offset that needs to be applied in order to
1351
1576
/// make the pointer aligned to `align`.
1352
1577
/// If it is not possible to align the pointer, the implementation returns
0 commit comments