summaryrefslogtreecommitdiffstats
path: root/library/core/src/ops/index.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /library/core/src/ops/index.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src/ops/index.rs')
-rw-r--r--library/core/src/ops/index.rs175
1 files changed, 175 insertions, 0 deletions
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
new file mode 100644
index 000000000..e2e569cb7
--- /dev/null
+++ b/library/core/src/ops/index.rs
@@ -0,0 +1,175 @@
+/// Used for indexing operations (`container[index]`) in immutable contexts.
+///
+/// `container[index]` is actually syntactic sugar for `*container.index(index)`,
+/// but only when used as an immutable value. If a mutable value is requested,
+/// [`IndexMut`] is used instead. This allows nice things such as
+/// `let value = v[index]` if the type of `value` implements [`Copy`].
+///
+/// # Examples
+///
+/// The following example implements `Index` on a read-only `NucleotideCount`
+/// container, enabling individual counts to be retrieved with index syntax.
+///
+/// ```
+/// 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> {
+ /// The returned type after indexing.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ type Output: ?Sized;
+
+ /// Performs the indexing (`container[index]`) operation.
+ ///
+ /// # Panics
+ ///
+ /// May panic if the index is out of bounds.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[track_caller]
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+/// Used for indexing operations (`container[index]`) in mutable contexts.
+///
+/// `container[index]` is actually syntactic sugar for
+/// `*container.index_mut(index)`, but only when used as a mutable value. If
+/// an immutable value is requested, the [`Index`] trait is used instead. This
+/// allows nice things such as `v[index] = value`.
+///
+/// # Examples
+///
+/// A very simple implementation of a `Balance` struct that has two sides, where
+/// each can be indexed mutably and immutably.
+///
+/// ```
+/// 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 {index:?}-side of balance immutably");
+/// 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 {index:?}-side of balance mutably");
+/// 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),
+/// };
+///
+/// // In this case, `balance[Side::Right]` is sugar for
+/// // `*balance.index(Side::Right)`, since we are only *reading*
+/// // `balance[Side::Right]`, not writing it.
+/// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5));
+///
+/// // However, in this case `balance[Side::Left]` is sugar for
+/// // `*balance.index_mut(Side::Left)`, since we are writing
+/// // `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> {
+ /// Performs the mutable indexing (`container[index]`) operation.
+ ///
+ /// # Panics
+ ///
+ /// May panic if the index is out of bounds.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[track_caller]
+ fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
+}