1 | /// Used for indexing operations (`container[index]`) in immutable contexts. |
2 | /// |
3 | /// `container[index]` is actually syntactic sugar for `*container.index(index)`, |
4 | /// but only when used as an immutable value. If a mutable value is requested, |
5 | /// [`IndexMut`] is used instead. This allows nice things such as |
6 | /// `let value = v[index]` if the type of `value` implements [`Copy`]. |
7 | /// |
8 | /// # Examples |
9 | /// |
10 | /// The following example implements `Index` on a read-only `NucleotideCount` |
11 | /// container, enabling individual counts to be retrieved with index syntax. |
12 | /// |
13 | /// ``` |
14 | /// use std::ops::Index; |
15 | /// |
16 | /// enum Nucleotide { |
17 | /// A, |
18 | /// C, |
19 | /// G, |
20 | /// T, |
21 | /// } |
22 | /// |
23 | /// struct NucleotideCount { |
24 | /// a: usize, |
25 | /// c: usize, |
26 | /// g: usize, |
27 | /// t: usize, |
28 | /// } |
29 | /// |
30 | /// impl Index<Nucleotide> for NucleotideCount { |
31 | /// type Output = usize; |
32 | /// |
33 | /// fn index(&self, nucleotide: Nucleotide) -> &Self::Output { |
34 | /// match nucleotide { |
35 | /// Nucleotide::A => &self.a, |
36 | /// Nucleotide::C => &self.c, |
37 | /// Nucleotide::G => &self.g, |
38 | /// Nucleotide::T => &self.t, |
39 | /// } |
40 | /// } |
41 | /// } |
42 | /// |
43 | /// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12}; |
44 | /// assert_eq!(nucleotide_count[Nucleotide::A], 14); |
45 | /// assert_eq!(nucleotide_count[Nucleotide::C], 9); |
46 | /// assert_eq!(nucleotide_count[Nucleotide::G], 10); |
47 | /// assert_eq!(nucleotide_count[Nucleotide::T], 12); |
48 | /// ``` |
49 | #[lang = "index" ] |
50 | #[diagnostic::on_unimplemented( |
51 | message = "the type `{Self}` cannot be indexed by `{Idx}`" , |
52 | label = "`{Self}` cannot be indexed by `{Idx}`" |
53 | )] |
54 | #[stable (feature = "rust1" , since = "1.0.0" )] |
55 | #[doc (alias = "]" )] |
56 | #[doc (alias = "[" )] |
57 | #[doc (alias = "[]" )] |
58 | pub trait Index<Idx: ?Sized> { |
59 | /// The returned type after indexing. |
60 | #[stable (feature = "rust1" , since = "1.0.0" )] |
61 | #[rustc_diagnostic_item = "IndexOutput" ] |
62 | type Output: ?Sized; |
63 | |
64 | /// Performs the indexing (`container[index]`) operation. |
65 | /// |
66 | /// # Panics |
67 | /// |
68 | /// May panic if the index is out of bounds. |
69 | #[stable (feature = "rust1" , since = "1.0.0" )] |
70 | #[track_caller ] |
71 | fn index(&self, index: Idx) -> &Self::Output; |
72 | } |
73 | |
74 | /// Used for indexing operations (`container[index]`) in mutable contexts. |
75 | /// |
76 | /// `container[index]` is actually syntactic sugar for |
77 | /// `*container.index_mut(index)`, but only when used as a mutable value. If |
78 | /// an immutable value is requested, the [`Index`] trait is used instead. This |
79 | /// allows nice things such as `v[index] = value`. |
80 | /// |
81 | /// # Examples |
82 | /// |
83 | /// A very simple implementation of a `Balance` struct that has two sides, where |
84 | /// each can be indexed mutably and immutably. |
85 | /// |
86 | /// ``` |
87 | /// use std::ops::{Index, IndexMut}; |
88 | /// |
89 | /// #[derive(Debug)] |
90 | /// enum Side { |
91 | /// Left, |
92 | /// Right, |
93 | /// } |
94 | /// |
95 | /// #[derive(Debug, PartialEq)] |
96 | /// enum Weight { |
97 | /// Kilogram(f32), |
98 | /// Pound(f32), |
99 | /// } |
100 | /// |
101 | /// struct Balance { |
102 | /// pub left: Weight, |
103 | /// pub right: Weight, |
104 | /// } |
105 | /// |
106 | /// impl Index<Side> for Balance { |
107 | /// type Output = Weight; |
108 | /// |
109 | /// fn index(&self, index: Side) -> &Self::Output { |
110 | /// println!("Accessing {index:?}-side of balance immutably" ); |
111 | /// match index { |
112 | /// Side::Left => &self.left, |
113 | /// Side::Right => &self.right, |
114 | /// } |
115 | /// } |
116 | /// } |
117 | /// |
118 | /// impl IndexMut<Side> for Balance { |
119 | /// fn index_mut(&mut self, index: Side) -> &mut Self::Output { |
120 | /// println!("Accessing {index:?}-side of balance mutably" ); |
121 | /// match index { |
122 | /// Side::Left => &mut self.left, |
123 | /// Side::Right => &mut self.right, |
124 | /// } |
125 | /// } |
126 | /// } |
127 | /// |
128 | /// let mut balance = Balance { |
129 | /// right: Weight::Kilogram(2.5), |
130 | /// left: Weight::Pound(1.5), |
131 | /// }; |
132 | /// |
133 | /// // In this case, `balance[Side::Right]` is sugar for |
134 | /// // `*balance.index(Side::Right)`, since we are only *reading* |
135 | /// // `balance[Side::Right]`, not writing it. |
136 | /// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5)); |
137 | /// |
138 | /// // However, in this case `balance[Side::Left]` is sugar for |
139 | /// // `*balance.index_mut(Side::Left)`, since we are writing |
140 | /// // `balance[Side::Left]`. |
141 | /// balance[Side::Left] = Weight::Kilogram(3.0); |
142 | /// ``` |
143 | #[lang = "index_mut" ] |
144 | #[rustc_on_unimplemented ( |
145 | on( |
146 | _Self = "&str" , |
147 | note = "you can use `.chars().nth()` or `.bytes().nth()` |
148 | see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" |
149 | ), |
150 | on( |
151 | _Self = "str" , |
152 | note = "you can use `.chars().nth()` or `.bytes().nth()` |
153 | see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" |
154 | ), |
155 | on( |
156 | _Self = "alloc::string::String" , |
157 | note = "you can use `.chars().nth()` or `.bytes().nth()` |
158 | see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" |
159 | ), |
160 | message = "the type `{Self}` cannot be mutably indexed by `{Idx}`" , |
161 | label = "`{Self}` cannot be mutably indexed by `{Idx}`" |
162 | )] |
163 | #[stable (feature = "rust1" , since = "1.0.0" )] |
164 | #[doc (alias = "[" )] |
165 | #[doc (alias = "]" )] |
166 | #[doc (alias = "[]" )] |
167 | pub trait IndexMut<Idx: ?Sized>: Index<Idx> { |
168 | /// Performs the mutable indexing (`container[index]`) operation. |
169 | /// |
170 | /// # Panics |
171 | /// |
172 | /// May panic if the index is out of bounds. |
173 | #[stable (feature = "rust1" , since = "1.0.0" )] |
174 | #[track_caller ] |
175 | fn index_mut(&mut self, index: Idx) -> &mut Self::Output; |
176 | } |
177 | |