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 | #[rustc_no_implicit_autorefs] |
71 | #[track_caller ] |
72 | fn index(&self, index: Idx) -> &Self::Output; |
73 | } |
74 | |
75 | /// Used for indexing operations (`container[index]`) in mutable contexts. |
76 | /// |
77 | /// `container[index]` is actually syntactic sugar for |
78 | /// `*container.index_mut(index)`, but only when used as a mutable value. If |
79 | /// an immutable value is requested, the [`Index`] trait is used instead. This |
80 | /// allows nice things such as `v[index] = value`. |
81 | /// |
82 | /// # Examples |
83 | /// |
84 | /// A very simple implementation of a `Balance` struct that has two sides, where |
85 | /// each can be indexed mutably and immutably. |
86 | /// |
87 | /// ``` |
88 | /// use std::ops::{Index, IndexMut}; |
89 | /// |
90 | /// #[derive(Debug)] |
91 | /// enum Side { |
92 | /// Left, |
93 | /// Right, |
94 | /// } |
95 | /// |
96 | /// #[derive(Debug, PartialEq)] |
97 | /// enum Weight { |
98 | /// Kilogram(f32), |
99 | /// Pound(f32), |
100 | /// } |
101 | /// |
102 | /// struct Balance { |
103 | /// pub left: Weight, |
104 | /// pub right: Weight, |
105 | /// } |
106 | /// |
107 | /// impl Index<Side> for Balance { |
108 | /// type Output = Weight; |
109 | /// |
110 | /// fn index(&self, index: Side) -> &Self::Output { |
111 | /// println!("Accessing {index:?}-side of balance immutably" ); |
112 | /// match index { |
113 | /// Side::Left => &self.left, |
114 | /// Side::Right => &self.right, |
115 | /// } |
116 | /// } |
117 | /// } |
118 | /// |
119 | /// impl IndexMut<Side> for Balance { |
120 | /// fn index_mut(&mut self, index: Side) -> &mut Self::Output { |
121 | /// println!("Accessing {index:?}-side of balance mutably" ); |
122 | /// match index { |
123 | /// Side::Left => &mut self.left, |
124 | /// Side::Right => &mut self.right, |
125 | /// } |
126 | /// } |
127 | /// } |
128 | /// |
129 | /// let mut balance = Balance { |
130 | /// right: Weight::Kilogram(2.5), |
131 | /// left: Weight::Pound(1.5), |
132 | /// }; |
133 | /// |
134 | /// // In this case, `balance[Side::Right]` is sugar for |
135 | /// // `*balance.index(Side::Right)`, since we are only *reading* |
136 | /// // `balance[Side::Right]`, not writing it. |
137 | /// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5)); |
138 | /// |
139 | /// // However, in this case `balance[Side::Left]` is sugar for |
140 | /// // `*balance.index_mut(Side::Left)`, since we are writing |
141 | /// // `balance[Side::Left]`. |
142 | /// balance[Side::Left] = Weight::Kilogram(3.0); |
143 | /// ``` |
144 | #[lang = "index_mut" ] |
145 | #[rustc_on_unimplemented ( |
146 | on( |
147 | Self = "&str" , |
148 | note = "you can use `.chars().nth()` or `.bytes().nth()` |
149 | see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" |
150 | ), |
151 | on( |
152 | Self = "str" , |
153 | note = "you can use `.chars().nth()` or `.bytes().nth()` |
154 | see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" |
155 | ), |
156 | on( |
157 | Self = "alloc::string::String" , |
158 | note = "you can use `.chars().nth()` or `.bytes().nth()` |
159 | see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" |
160 | ), |
161 | message = "the type `{Self}` cannot be mutably indexed by `{Idx}`" , |
162 | label = "`{Self}` cannot be mutably indexed by `{Idx}`" |
163 | )] |
164 | #[stable (feature = "rust1" , since = "1.0.0" )] |
165 | #[doc (alias = "[" )] |
166 | #[doc (alias = "]" )] |
167 | #[doc (alias = "[]" )] |
168 | pub trait IndexMut<Idx: ?Sized>: Index<Idx> { |
169 | /// Performs the mutable indexing (`container[index]`) operation. |
170 | /// |
171 | /// # Panics |
172 | /// |
173 | /// May panic if the index is out of bounds. |
174 | #[stable (feature = "rust1" , since = "1.0.0" )] |
175 | #[rustc_no_implicit_autorefs] |
176 | #[track_caller ] |
177 | fn index_mut(&mut self, index: Idx) -> &mut Self::Output; |
178 | } |
179 | |