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
/// 用于在不可变上下文中索引操作 (`container[index]`)。
///
/// `container[index]` 实际上是 `*container.index(index)` 的语法糖,但仅在用作不可变值时使用。
/// 如果请求一个可变值,则使用 [`IndexMut`]。
/// 如果 `value` 的类型实现 [`Copy`],则这允许使用诸如 `let value = v[index]` 之类的好东西。
///
/// # Examples
///
/// 下面的示例在只读 `NucleotideCount` 容器上实现 `Index`,从而可以使用索引语法检索单个计数。
///
///
/// ```
/// use std::ops::Index;
///
/// enum Nucleotide {
/// A,
/// C,
/// G,
/// T,
/// }
///
/// struct NucleotideCount {
/// a: usize,
/// c: usize,
/// g: usize,
/// t: usize,
/// }
///
/// impl Index<Nucleotide> for NucleotideCount {
/// type Output = usize;
///
/// fn index(&self, nucleotide: Nucleotide) -> &Self::Output {
/// match nucleotide {
/// Nucleotide::A => &self.a,
/// Nucleotide::C => &self.c,
/// Nucleotide::G => &self.g,
/// Nucleotide::T => &self.t,
/// }
/// }
/// }
///
/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12};
/// assert_eq!(nucleotide_count[Nucleotide::A], 14);
/// assert_eq!(nucleotide_count[Nucleotide::C], 9);
/// assert_eq!(nucleotide_count[Nucleotide::G], 10);
/// assert_eq!(nucleotide_count[Nucleotide::T], 12);
/// ```
///
#[lang = "index"]
#[rustc_on_unimplemented(
message = "the type `{Self}` cannot be indexed by `{Idx}`",
label = "`{Self}` cannot be indexed by `{Idx}`"
)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "]")]
#[doc(alias = "[")]
#[doc(alias = "[]")]
pub trait Index<Idx: ?Sized> {
/// 索引后返回的类型。
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "IndexOutput"]
type Output: ?Sized;
/// 执行索引 (`container[index]`) 操作。
///
/// # Panics
///
/// 如果索引越界,则可能为 panic。
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
fn index(&self, index: Idx) -> &Self::Output;
}
/// 用于可变上下文中的索引操作 (`container[index]`)。
///
/// `container[index]` 实际上是 `*container.index_mut(index)` 的语法糖,但仅在用作可变值时使用。
/// 如果请求一个不可变值,则使用 [`Index`] trait。
/// 这允许使用诸如 `v[index] = value` 之类的好东西。
///
/// # Examples
///
/// `Balance` 结构体的非常简单的实现,它具有两个面,每个面都可以可变和不可变地进行索引。
///
/// ```
/// use std::ops::{Index, IndexMut};
///
/// #[derive(Debug)]
/// enum Side {
/// Left,
/// Right,
/// }
///
/// #[derive(Debug, PartialEq)]
/// enum Weight {
/// Kilogram(f32),
/// Pound(f32),
/// }
///
/// struct Balance {
/// pub left: Weight,
/// pub right: Weight,
/// }
///
/// impl Index<Side> for Balance {
/// type Output = Weight;
///
/// fn index(&self, index: Side) -> &Self::Output {
/// println!("Accessing {index:?}-side of balance immutably");
/// match index {
/// Side::Left => &self.left,
/// Side::Right => &self.right,
/// }
/// }
/// }
///
/// impl IndexMut<Side> for Balance {
/// fn index_mut(&mut self, index: Side) -> &mut Self::Output {
/// println!("Accessing {index:?}-side of balance mutably");
/// match index {
/// Side::Left => &mut self.left,
/// Side::Right => &mut self.right,
/// }
/// }
/// }
///
/// let mut balance = Balance {
/// right: Weight::Kilogram(2.5),
/// left: Weight::Pound(1.5),
/// };
///
/// // 在这种情况下,`balance[Side::Right]` 是 `*balance.index(Side::Right)` 的糖,因为我们只是* 读*`balance[Side::Right]`,而不是写 `balance[Side::Right]`。
/////
/////
/// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5));
///
/// // 但是,在这种情况下,`balance[Side::Left]` 是 `*balance.index_mut(Side::Left)` 的糖,因为我们正在编写 `balance[Side::Left]`。
/////
/////
/// balance[Side::Left] = Weight::Kilogram(3.0);
/// ```
///
///
#[lang = "index_mut"]
#[rustc_on_unimplemented(
on(
_Self = "&str",
note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
on(
_Self = "str",
note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
on(
_Self = "std::string::String",
note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
message = "the type `{Self}` cannot be mutably indexed by `{Idx}`",
label = "`{Self}` cannot be mutably indexed by `{Idx}`"
)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "[")]
#[doc(alias = "]")]
#[doc(alias = "[]")]
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
/// 执行可变索引 (`container[index]`) 操作。
///
/// # Panics
///
/// 如果索引越界,则可能为 panic。
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}