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