|
1 | 1 | //! Free functions to create `&[T]` and `&mut [T]`.
|
2 | 2 |
|
3 | 3 | use crate::array;
|
| 4 | +use crate::ops::Range; |
4 | 5 | use crate::ptr;
|
5 | 6 |
|
6 | 7 | /// Forms a slice from a pointer and a length.
|
@@ -177,3 +178,113 @@ pub const fn from_ref<T>(s: &T) -> &[T] {
|
177 | 178 | pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
|
178 | 179 | array::from_mut(s)
|
179 | 180 | }
|
| 181 | + |
| 182 | +/// Forms a slice from a pointer range. |
| 183 | +/// |
| 184 | +/// This function is useful for interacting with foreign interfaces which |
| 185 | +/// use two pointers to refer to a range of elements in memory, as is |
| 186 | +/// common in C++. |
| 187 | +/// |
| 188 | +/// # Safety |
| 189 | +/// |
| 190 | +/// Behavior is undefined if any of the following conditions are violated: |
| 191 | +/// |
| 192 | +/// * The `start` pointer of the range must be a [valid] and properly aligned pointer |
| 193 | +/// to the first element of a slice. |
| 194 | +/// |
| 195 | +/// * The `end` pointer must be a [valid] and properly aligned pointer to *one past* |
| 196 | +/// the last element, such that the offset from the end to the start pointer is |
| 197 | +/// the length of the slice. |
| 198 | +/// |
| 199 | +/// * The range must contain `N` consecutive properly initialized values of type `T`: |
| 200 | +/// |
| 201 | +/// * The entire memory range of this slice must be contained within a single allocated object! |
| 202 | +/// Slices can never span across multiple allocated objects. |
| 203 | +/// |
| 204 | +/// * The memory referenced by the returned slice must not be mutated for the duration |
| 205 | +/// of lifetime `'a`, except inside an `UnsafeCell`. |
| 206 | +/// |
| 207 | +/// * The total length of the range must be no larger than `isize::MAX`. |
| 208 | +/// See the safety documentation of [`pointer::offset`]. |
| 209 | +/// |
| 210 | +/// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements. |
| 211 | +/// |
| 212 | +/// # Caveat |
| 213 | +/// |
| 214 | +/// The lifetime for the returned slice is inferred from its usage. To |
| 215 | +/// prevent accidental misuse, it's suggested to tie the lifetime to whichever |
| 216 | +/// source lifetime is safe in the context, such as by providing a helper |
| 217 | +/// function taking the lifetime of a host value for the slice, or by explicit |
| 218 | +/// annotation. |
| 219 | +/// |
| 220 | +/// # Examples |
| 221 | +/// |
| 222 | +/// ``` |
| 223 | +/// #![feature(slice_from_ptr_range)] |
| 224 | +/// |
| 225 | +/// use core::slice; |
| 226 | +/// |
| 227 | +/// let x = [1, 2, 3]; |
| 228 | +/// let range = x.as_ptr_range(); |
| 229 | +/// |
| 230 | +/// unsafe { |
| 231 | +/// assert_eq!(slice::from_ptr_range(range), &x); |
| 232 | +/// } |
| 233 | +/// ``` |
| 234 | +/// |
| 235 | +/// [valid]: ptr#safety |
| 236 | +#[unstable(feature = "slice_from_ptr_range", issue = "89792")] |
| 237 | +pub unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] { |
| 238 | + // SAFETY: the caller must uphold the safety contract for `from_ptr_range`. |
| 239 | + unsafe { from_raw_parts(range.start, range.end.offset_from(range.start) as usize) } |
| 240 | +} |
| 241 | + |
| 242 | +/// Performs the same functionality as [`from_ptr_range`], except that a |
| 243 | +/// mutable slice is returned. |
| 244 | +/// |
| 245 | +/// # Safety |
| 246 | +/// |
| 247 | +/// Behavior is undefined if any of the following conditions are violated: |
| 248 | +/// |
| 249 | +/// * The `start` pointer of the range must be a [valid] and properly aligned pointer |
| 250 | +/// to the first element of a slice. |
| 251 | +/// |
| 252 | +/// * The `end` pointer must be a [valid] and properly aligned pointer to *one past* |
| 253 | +/// the last element, such that the offset from the end to the start pointer is |
| 254 | +/// the length of the slice. |
| 255 | +/// |
| 256 | +/// * The range must contain `N` consecutive properly initialized values of type `T`: |
| 257 | +/// |
| 258 | +/// * The entire memory range of this slice must be contained within a single allocated object! |
| 259 | +/// Slices can never span across multiple allocated objects. |
| 260 | +/// |
| 261 | +/// * The memory referenced by the returned slice must not be accessed through any other pointer |
| 262 | +/// (not derived from the return value) for the duration of lifetime `'a`. |
| 263 | +/// Both read and write accesses are forbidden. |
| 264 | +/// |
| 265 | +/// * The total length of the range must be no larger than `isize::MAX`. |
| 266 | +/// See the safety documentation of [`pointer::offset`]. |
| 267 | +/// |
| 268 | +/// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements. |
| 269 | +/// |
| 270 | +/// # Examples |
| 271 | +/// |
| 272 | +/// ``` |
| 273 | +/// #![feature(slice_from_ptr_range)] |
| 274 | +/// |
| 275 | +/// use core::slice; |
| 276 | +/// |
| 277 | +/// let mut x = [1, 2, 3]; |
| 278 | +/// let range = x.as_mut_ptr_range(); |
| 279 | +/// |
| 280 | +/// unsafe { |
| 281 | +/// assert_eq!(slice::from_mut_ptr_range(range), &mut [1, 2, 3]); |
| 282 | +/// } |
| 283 | +/// ``` |
| 284 | +/// |
| 285 | +/// [valid]: ptr#safety |
| 286 | +#[unstable(feature = "slice_from_ptr_range", issue = "89792")] |
| 287 | +pub unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] { |
| 288 | + // SAFETY: the caller must uphold the safety contract for `from_mut_ptr_range`. |
| 289 | + unsafe { from_raw_parts_mut(range.start, range.end.offset_from(range.start) as usize) } |
| 290 | +} |
0 commit comments