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
//! 自由函数来创建 `&[T]` 和 `&mut [T]`。

use crate::array;
use crate::intrinsics::is_aligned_and_not_null;
use crate::mem;
use crate::ptr;

/// 根据指针和长度形成切片。
///
/// `len` 参数是 **元素** 的数量,而不是字节数。
///
/// # Safety
///
/// 如果违反以下任一条件,则行为是未定义的:
///
/// * `data` 必须是 [有效][valid] 的,才能读取许多字节的 `len * mem::size_of::<T>()`,并且必须正确对齐。这尤其意味着:
///
///     * 该切片的整个存储范围必须包含在一个分配的对象中!
///       切片永远不能跨越多个分配的对象。请参见 [below](#incorrect-usage) 以获取错误地未考虑到这一点的示例。
///     * `data` 必须为非 null,并且即使对于零长度的切片也必须对齐。
///     这样做的一个原因是,枚举布局优化可能依赖于对齐的引用 (包括任何长度的切片) 和非空值,以将它们与其他数据区分开。
///     您可以使用 [`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` 函数是 **unsound** ⚠️
///
/// ```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")]
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
    debug_assert!(
        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
        "attempt to create slice covering at least half the address space"
    );
    // SAFETY: 调用者必须坚持 `from_raw_parts` 的安全保证。
    unsafe { &*ptr::slice_from_raw_parts(data, len) }
}

/// 执行与 [`from_raw_parts`] 相同的功能,除了返回可变切片。
///
/// # Safety
///
/// 如果违反以下任一条件,则行为是未定义的:
///
/// * `data` `len * mem::size_of::<T>()` 的多个字节的读取和写入必须是 [有效][valid] 的,并且必须正确对齐。这尤其意味着:
///
///     * 该切片的整个存储范围必须包含在一个分配的对象中!
///       切片永远不能跨越多个分配的对象。
///     * `data` 必须为非 null,并且即使对于零长度的切片也必须对齐。
///     这样做的一个原因是,枚举布局优化可能依赖于对齐的引用 (包括任何长度的切片) 和非空值,以将它们与其他数据区分开。
///
///     您可以使用 [`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")]
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
    debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
    debug_assert!(
        mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
        "attempt to create slice covering at least half the address space"
    );
    // SAFETY: 调用者必须坚持 `from_raw_parts_mut` 的安全保证。
    unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
}

/// 将引用转换为 T 转换为长度为 1 的切片 (不进行复制)。
#[stable(feature = "from_ref", since = "1.28.0")]
pub fn from_ref<T>(s: &T) -> &[T] {
    array::from_ref(s)
}

/// 将引用转换为 T 转换为长度为 1 的切片 (不进行复制)。
#[stable(feature = "from_ref", since = "1.28.0")]
pub fn from_mut<T>(s: &mut T) -> &mut [T] {
    array::from_mut(s)
}