@@ -28,7 +28,7 @@ use crate::fmt;
28
28
use crate :: intrinsics:: { assume, exact_div, unchecked_sub, is_aligned_and_not_null} ;
29
29
use crate :: isize;
30
30
use crate :: iter:: * ;
31
- use crate :: ops:: { FnMut , self } ;
31
+ use crate :: ops:: { FnMut , Range , self } ;
32
32
use crate :: option:: Option ;
33
33
use crate :: option:: Option :: { None , Some } ;
34
34
use crate :: result:: Result ;
@@ -407,6 +407,86 @@ impl<T> [T] {
407
407
self as * mut [ T ] as * mut T
408
408
}
409
409
410
+ /// Returns the two raw pointers spanning the slice.
411
+ ///
412
+ /// The returned range is half-open, which means that the end pointer
413
+ /// points *one past* the last element of the slice. This way, an empty
414
+ /// slice is represented by two equal pointers, and the difference between
415
+ /// the two pointers represents the size of the size.
416
+ ///
417
+ /// See [`as_ptr`] for warnings on using these pointers. The end pointer
418
+ /// requires extra caution, as it does not point to a valid element in the
419
+ /// slice.
420
+ ///
421
+ /// This function is useful for interacting with foreign interfaces which
422
+ /// use two pointers to refer to a range of elements in memory, as is
423
+ /// common in C++.
424
+ ///
425
+ /// It can also be useful to check if a pointer to an element refers to an
426
+ /// element of this slice:
427
+ ///
428
+ /// ```
429
+ /// #![feature(slice_ptr_range)]
430
+ ///
431
+ /// let a = [1, 2, 3];
432
+ /// let x = &a[1] as *const _;
433
+ /// let y = &5 as *const _;
434
+ ///
435
+ /// assert!(a.as_ptr_range().contains(&x));
436
+ /// assert!(!a.as_ptr_range().contains(&y));
437
+ /// ```
438
+ ///
439
+ /// [`as_ptr`]: #method.as_ptr
440
+ #[ unstable( feature = "slice_ptr_range" , issue = "65807" ) ]
441
+ #[ inline]
442
+ pub fn as_ptr_range ( & self ) -> Range < * const T > {
443
+ // The `add` here is safe, because:
444
+ //
445
+ // - Both pointers are part of the same object, as pointing directly
446
+ // past the object also counts.
447
+ //
448
+ // - The size of the slice is never larger than isize::MAX bytes, as
449
+ // noted here:
450
+ // - https://github.com/rust-lang/unsafe-code-guidelines/issues/102#issuecomment-473340447
451
+ // - https://doc.rust-lang.org/reference/behavior-considered-undefined.html
452
+ // - https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html#safety
453
+ // (This doesn't seem normative yet, but the very same assumption is
454
+ // made in many places, including the Index implementation of slices.)
455
+ //
456
+ // - There is no wrapping around involved, as slices do not wrap past
457
+ // the end of the address space.
458
+ //
459
+ // See the documentation of pointer::add.
460
+ let start = self . as_ptr ( ) ;
461
+ let end = unsafe { start. add ( self . len ( ) ) } ;
462
+ start..end
463
+ }
464
+
465
+ /// Returns the two unsafe mutable pointers spanning the slice.
466
+ ///
467
+ /// The returned range is half-open, which means that the end pointer
468
+ /// points *one past* the last element of the slice. This way, an empty
469
+ /// slice is represented by two equal pointers, and the difference between
470
+ /// the two pointers represents the size of the size.
471
+ ///
472
+ /// See [`as_mut_ptr`] for warnings on using these pointers. The end
473
+ /// pointer requires extra caution, as it does not point to a valid element
474
+ /// in the slice.
475
+ ///
476
+ /// This function is useful for interacting with foreign interfaces which
477
+ /// use two pointers to refer to a range of elements in memory, as is
478
+ /// common in C++.
479
+ ///
480
+ /// [`as_mut_ptr`]: #method.as_mut_ptr
481
+ #[ unstable( feature = "slice_ptr_range" , issue = "65807" ) ]
482
+ #[ inline]
483
+ pub fn as_mut_ptr_range ( & mut self ) -> Range < * mut T > {
484
+ // See as_ptr_range() above for why `add` here is safe.
485
+ let start = self . as_mut_ptr ( ) ;
486
+ let end = unsafe { start. add ( self . len ( ) ) } ;
487
+ start..end
488
+ }
489
+
410
490
/// Swaps two elements in the slice.
411
491
///
412
492
/// # Arguments
0 commit comments