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
/// 用于在不可变上下文中索引操作 (`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")]
    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 {:?}-side of balance immutably", index);
///         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 {:?}-side of balance mutably", index);
///         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;
}