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