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)) }
}