1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
//! 创建 `&[T]` 和 `&mut [T]` 的 free 函数。
use crate::array;
use crate::intrinsics::{
assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
};
use crate::ops::Range;
use crate::ptr;
/// 根据指针和长度形成切片。
///
/// `len` 参数是 **元素** 的数量,而不是字节数。
///
/// # Safety
///
/// 如果违反以下任一条件,则行为是未定义的:
///
/// * 对于 `len * mem::size_of::<T>()` 多个字节的读取,`data` 必须是 [valid],并且必须正确对齐。这尤其意味着:
///
/// * 该切片的整个存储范围必须包含在一个分配的对象中!
/// 切片永远不能跨越多个分配的对象。请参见 [下文](#incorrect-usage) 了解一个没有考虑到这一点的错误示例。
/// * 即使对于零长度切片,`data` 也必须非空且对齐。
/// 这样做的一个原因是,枚举布局优化可能依赖于对齐的引用 (包括任何长度的切片) 和非空值,以将它们与其他数据区分开。
/// 您可以使用 [`NonNull::dangling()`] 获得可用作零长度切片的 `data` 的指针。
///
/// * `data` 必须指向 `len` 类型的 `T` 类型的连续正确初始化值。
///
/// * 返回的切片引用的内存在生命周期 `'a` 期间不得更改,除非在 `UnsafeCell` 内部。
///
/// * 切片的总大小 `len * mem::size_of::<T>()` 必须不大于 `isize::MAX`。
/// 请参见 [`pointer::offset`] 的安全文档。
///
/// # Caveat
///
/// 从使用中可以推断出返回切片的生命周期。
/// 为防止意外滥用,建议将生命周期与生命周期中任何安全的来源联系起来,例如通过提供一个辅助函数,获取切片的宿主值的生命周期,或通过明确的注解法。
///
///
/// # Examples
///
/// ```
/// use std::slice;
///
/// // 显示单个元素的切片
/// let x = 42;
/// let ptr = &x as *const _;
/// let slice = unsafe { slice::from_raw_parts(ptr, 1) };
/// assert_eq!(slice[0], 42);
/// ```
///
/// ### 用法不正确
///
/// 下面的 `join_slices` 函数是不健全的 ⚠️
///
/// ```rust,no_run
/// use std::slice;
///
/// fn join_slices<'a, T>(fst: &'a [T], snd: &'a [T]) -> &'a [T] {
/// let fst_end = fst.as_ptr().wrapping_add(fst.len());
/// let snd_start = snd.as_ptr();
/// assert_eq!(fst_end, snd_start, "Slices must be contiguous!");
/// unsafe {
/// // 上面的断言确保 `fst` 和 `snd` 是连续的,但是它们仍可能包含在 _different allocated objects_ 中,在这种情况下,创建此切片是未定义的行为。
/////
/////
/// slice::from_raw_parts(fst.as_ptr(), fst.len() + snd.len())
/// }
/// }
///
/// fn main() {
/// // `a` 和 `b` 是不同的分配对象...
/// let a = 42;
/// let b = 27;
/// // ... 尽管如此,它仍然可以在内存中连续布局: | 一个 | b |
/// let _ = join_slices(slice::from_ref(&a), slice::from_ref(&b)); // UB
/// }
/// ```
///
/// [valid]: ptr#safety
/// [`NonNull::dangling()`]: ptr::NonNull::dangling
///
///
///
///
///
///
///
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
#[must_use]
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
// SAFETY: 调用者必须遵守 `from_raw_parts` 的安全保证。
unsafe {
assert_unsafe_precondition!(
"slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
[T](data: *const T, len: usize) => is_aligned_and_not_null(data)
&& is_valid_allocation_size::<T>(len)
);
&*ptr::slice_from_raw_parts(data, len)
}
}
/// 执行与 [`from_raw_parts`] 相同的功能,除了返回可变切片。
///
/// # Safety
///
/// 如果违反以下任一条件,则行为是未定义的:
///
/// * 对于 `len * mem::size_of::<T>()` 多个字节的读取和写入,`data` 必须是 [valid],并且必须正确对齐。这尤其意味着:
///
/// * 该切片的整个存储范围必须包含在一个分配的对象中!
/// 切片永远不能跨越多个分配的对象。
/// * 即使对于零长度切片,`data` 也必须非空且对齐。
/// 这样做的一个原因是,枚举布局优化可能依赖于对齐的引用 (包括任何长度的切片) 和非空值,以将它们与其他数据区分开。
///
/// 您可以使用 [`NonNull::dangling()`] 获得可用作零长度切片的 `data` 的指针。
///
/// * `data` 必须指向 `len` 类型的 `T` 类型的连续正确初始化值。
///
/// * 在生命周期 `'a` 的持续时间内,不得通过任何其他指针 (不是从返回值派生) 访问返回的切片引用的内存。
/// 读取和写入访问均被禁止。
///
/// * 切片的总大小 `len * mem::size_of::<T>()` 必须不大于 `isize::MAX`。
/// 请参见 [`pointer::offset`] 的安全文档。
///
/// [valid]: ptr#safety
/// [`NonNull::dangling()`]: ptr::NonNull::dangling
///
///
///
///
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
#[must_use]
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
// SAFETY: 调用者必须遵守 `from_raw_parts_mut` 的安全保证。
unsafe {
assert_unsafe_precondition!(
"slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
[T](data: *mut T, len: usize) => is_aligned_and_not_null(data)
&& is_valid_allocation_size::<T>(len)
);
&mut *ptr::slice_from_raw_parts_mut(data, len)
}
}
/// 将引用转换为 T 转换为长度为 1 的切片 (不进行复制)。
#[stable(feature = "from_ref", since = "1.28.0")]
#[rustc_const_stable(feature = "const_slice_from_ref_shared", since = "1.63.0")]
#[must_use]
pub const fn from_ref<T>(s: &T) -> &[T] {
array::from_ref(s)
}
/// 将引用转换为 T 转换为长度为 1 的切片 (不进行复制)。
#[stable(feature = "from_ref", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")]
#[must_use]
pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
array::from_mut(s)
}
/// 从指针范围形成一个切片。
///
/// 此函数对于与外部接口进行交互很有用,该外部接口使用两个指针来引用内存中的一系列元素,这在 C++ 中很常见。
///
/// # Safety
///
/// 如果违反以下任一条件,则行为是未定义的:
///
/// * 范围的 `start` 指针必须是 [valid] 并正确对齐指向切片的第一个元素的指针。
///
/// * `end` 指针必须是 [valid] 且正确对齐的指针,指向*一个过去*最后一个元素,这样从末尾到起始指针的偏移量就是切片的长度。
///
/// * 范围必须包含 `N` 类型 `T` 的连续正确初始化值:
///
/// * 该切片的整个存储范围必须包含在一个分配的对象中!
/// 切片永远不能跨越多个分配的对象。
///
/// * 返回的切片引用的内存在生命周期 `'a` 期间不得更改,除非在 `UnsafeCell` 内部。
///
/// * 范围的总长度不得大于 `isize::MAX`。
/// 请参见 [`pointer::offset`] 的安全文档。
///
/// 请注意,从 [`slice::as_ptr_range`] 创建的范围满足这些要求。
///
/// # Panics
///
/// 如果 `T` 是一个零大小的类型 (“ZST”),这个函数就会出现 panic。
///
/// # Caveat
///
/// 从使用中可以推断出返回切片的生命周期。
/// 为防止意外滥用,建议将生命周期与生命周期中任何安全的来源联系起来,例如通过提供一个辅助函数,获取切片的宿主值的生命周期,或通过明确的注解法。
///
///
/// # Examples
///
/// ```
/// #![feature(slice_from_ptr_range)]
///
/// use core::slice;
///
/// let x = [1, 2, 3];
/// let range = x.as_ptr_range();
///
/// unsafe {
/// assert_eq!(slice::from_ptr_range(range), &x);
/// }
/// ```
///
/// [valid]: ptr#safety
///
///
///
///
///
///
///
///
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
#[rustc_const_unstable(feature = "const_slice_from_ptr_range", issue = "89792")]
pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
// SAFETY: 调用者必须维护 `from_ptr_range` 的安全保证。
unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
}
/// 从指针范围形成一个分割切片。
///
/// 这与 [`from_ptr_range`] 的功能相同,只是返回了一个不合法的切片。
///
/// 此函数对于与外部接口进行交互很有用,该外部接口使用两个指针来引用内存中的一系列元素,这在 C++ 中很常见。
///
/// # Safety
///
/// 如果违反以下任一条件,则行为是未定义的:
///
/// * 范围的 `start` 指针必须是 [valid] 并正确对齐指向切片的第一个元素的指针。
///
/// * `end` 指针必须是 [valid] 且正确对齐的指针,指向*一个过去*最后一个元素,这样从末尾到起始指针的偏移量就是切片的长度。
///
/// * 范围必须包含 `N` 类型 `T` 的连续正确初始化值:
///
/// * 该切片的整个存储范围必须包含在一个分配的对象中!
/// 切片永远不能跨越多个分配的对象。
///
/// * 在生命周期 `'a` 的持续时间内,不得通过任何其他指针 (不是从返回值派生) 访问返回的切片引用的内存。
/// 读取和写入访问均被禁止。
///
/// * 范围的总长度不得大于 `isize::MAX`。
/// 请参见 [`pointer::offset`] 的安全文档。
///
/// 请注意,从 [`slice::as_mut_ptr_range`] 创建的范围满足这些要求。
///
/// # Panics
///
/// 如果 `T` 是一个零大小的类型 (“ZST”),这个函数就会出现 panic。
///
/// # Caveat
///
/// 从使用中可以推断出返回切片的生命周期。
/// 为防止意外滥用,建议将生命周期与生命周期中任何安全的来源联系起来,例如通过提供一个辅助函数,获取切片的宿主值的生命周期,或通过明确的注解法。
///
///
/// # Examples
///
/// ```
/// #![feature(slice_from_ptr_range)]
///
/// use core::slice;
///
/// let mut x = [1, 2, 3];
/// let range = x.as_mut_ptr_range();
///
/// unsafe {
/// assert_eq!(slice::from_mut_ptr_range(range), &mut [1, 2, 3]);
/// }
/// ```
///
/// [valid]: ptr#safety
///
///
///
///
///
///
///
///
///
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
#[rustc_const_unstable(feature = "const_slice_from_mut_ptr_range", issue = "89792")]
pub const unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] {
// SAFETY: 调用者必须维护 `from_mut_ptr_range` 的安全保证。
unsafe { from_raw_parts_mut(range.start, range.end.sub_ptr(range.start)) }
}