Skip to content

Commit 8282873

Browse files
authored
Merge pull request #132 from cuviper/direct-index
Implement direct usize indexing
2 parents 8ddc4f1 + 4d4fc0a commit 8282873

File tree

3 files changed

+194
-2
lines changed

3 files changed

+194
-2
lines changed

src/map.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,28 @@ impl<K, V, S> IntoIterator for IndexMap<K, V, S> {
993993
}
994994
}
995995

996+
/// Access `IndexMap` values corresponding to a key.
997+
///
998+
/// # Examples
999+
///
1000+
/// ```
1001+
/// use indexmap::IndexMap;
1002+
///
1003+
/// let mut map = IndexMap::new();
1004+
/// for word in "Lorem ipsum dolor sit amet".split_whitespace() {
1005+
/// map.insert(word.to_lowercase(), word.to_uppercase());
1006+
/// }
1007+
/// assert_eq!(map["lorem"], "LOREM");
1008+
/// assert_eq!(map["ipsum"], "IPSUM");
1009+
/// ```
1010+
///
1011+
/// ```should_panic
1012+
/// use indexmap::IndexMap;
1013+
///
1014+
/// let mut map = IndexMap::new();
1015+
/// map.insert("foo", 1);
1016+
/// println!("{:?}", map["bar"]); // panics!
1017+
/// ```
9961018
impl<K, V, Q: ?Sized, S> Index<&Q> for IndexMap<K, V, S>
9971019
where
9981020
Q: Hash + Equivalent<K>,
@@ -1001,28 +1023,138 @@ where
10011023
{
10021024
type Output = V;
10031025

1026+
/// Returns a reference to the value corresponding to the supplied `key`.
1027+
///
10041028
/// ***Panics*** if `key` is not present in the map.
10051029
fn index(&self, key: &Q) -> &V {
10061030
self.get(key).expect("IndexMap: key not found")
10071031
}
10081032
}
10091033

1034+
/// Access `IndexMap` values corresponding to a key.
1035+
///
10101036
/// Mutable indexing allows changing / updating values of key-value
10111037
/// pairs that are already present.
10121038
///
10131039
/// You can **not** insert new pairs with index syntax, use `.insert()`.
1040+
///
1041+
/// # Examples
1042+
///
1043+
/// ```
1044+
/// use indexmap::IndexMap;
1045+
///
1046+
/// let mut map = IndexMap::new();
1047+
/// for word in "Lorem ipsum dolor sit amet".split_whitespace() {
1048+
/// map.insert(word.to_lowercase(), word.to_string());
1049+
/// }
1050+
/// let lorem = &mut map["lorem"];
1051+
/// assert_eq!(lorem, "Lorem");
1052+
/// lorem.retain(char::is_lowercase);
1053+
/// assert_eq!(map["lorem"], "orem");
1054+
/// ```
1055+
///
1056+
/// ```should_panic
1057+
/// use indexmap::IndexMap;
1058+
///
1059+
/// let mut map = IndexMap::new();
1060+
/// map.insert("foo", 1);
1061+
/// map["bar"] = 1; // panics!
1062+
/// ```
10141063
impl<K, V, Q: ?Sized, S> IndexMut<&Q> for IndexMap<K, V, S>
10151064
where
10161065
Q: Hash + Equivalent<K>,
10171066
K: Hash + Eq,
10181067
S: BuildHasher,
10191068
{
1069+
/// Returns a mutable reference to the value corresponding to the supplied `key`.
1070+
///
10201071
/// ***Panics*** if `key` is not present in the map.
10211072
fn index_mut(&mut self, key: &Q) -> &mut V {
10221073
self.get_mut(key).expect("IndexMap: key not found")
10231074
}
10241075
}
10251076

1077+
/// Access `IndexMap` values at indexed positions.
1078+
///
1079+
/// # Examples
1080+
///
1081+
/// ```
1082+
/// use indexmap::IndexMap;
1083+
///
1084+
/// let mut map = IndexMap::new();
1085+
/// for word in "Lorem ipsum dolor sit amet".split_whitespace() {
1086+
/// map.insert(word.to_lowercase(), word.to_uppercase());
1087+
/// }
1088+
/// assert_eq!(map[0], "LOREM");
1089+
/// assert_eq!(map[1], "IPSUM");
1090+
/// map.reverse();
1091+
/// assert_eq!(map[0], "AMET");
1092+
/// assert_eq!(map[1], "SIT");
1093+
/// map.sort_keys();
1094+
/// assert_eq!(map[0], "AMET");
1095+
/// assert_eq!(map[1], "DOLOR");
1096+
/// ```
1097+
///
1098+
/// ```should_panic
1099+
/// use indexmap::IndexMap;
1100+
///
1101+
/// let mut map = IndexMap::new();
1102+
/// map.insert("foo", 1);
1103+
/// println!("{:?}", map[10]); // panics!
1104+
/// ```
1105+
impl<K, V, S> Index<usize> for IndexMap<K, V, S> {
1106+
type Output = V;
1107+
1108+
/// Returns a reference to the value at the supplied `index`.
1109+
///
1110+
/// ***Panics*** if `index` is out of bounds.
1111+
fn index(&self, index: usize) -> &V {
1112+
self.get_index(index)
1113+
.expect("IndexMap: index out of bounds")
1114+
.1
1115+
}
1116+
}
1117+
1118+
/// Access `IndexMap` values at indexed positions.
1119+
///
1120+
/// Mutable indexing allows changing / updating indexed values
1121+
/// that are already present.
1122+
///
1123+
/// You can **not** insert new values with index syntax, use `.insert()`.
1124+
///
1125+
/// # Examples
1126+
///
1127+
/// ```
1128+
/// use indexmap::IndexMap;
1129+
///
1130+
/// let mut map = IndexMap::new();
1131+
/// for word in "Lorem ipsum dolor sit amet".split_whitespace() {
1132+
/// map.insert(word.to_lowercase(), word.to_string());
1133+
/// }
1134+
/// let lorem = &mut map[0];
1135+
/// assert_eq!(lorem, "Lorem");
1136+
/// lorem.retain(char::is_lowercase);
1137+
/// assert_eq!(map["lorem"], "orem");
1138+
/// ```
1139+
///
1140+
/// ```should_panic
1141+
/// use indexmap::IndexMap;
1142+
///
1143+
/// let mut map = IndexMap::new();
1144+
/// map.insert("foo", 1);
1145+
/// map[10] = 1; // panics!
1146+
/// ```
1147+
impl<K, V, S> IndexMut<usize> for IndexMap<K, V, S> {
1148+
/// Returns a mutable reference to the value at the supplied `index`.
1149+
///
1150+
/// ***Panics*** if `index` is out of bounds.
1151+
fn index_mut(&mut self, index: usize) -> &mut V {
1152+
self.get_index_mut(index)
1153+
.expect("IndexMap: index out of bounds")
1154+
.1
1155+
}
1156+
}
1157+
10261158
impl<K, V, S> FromIterator<(K, V)> for IndexMap<K, V, S>
10271159
where
10281160
K: Hash + Eq,

src/set.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use core::cmp::Ordering;
1111
use core::fmt;
1212
use core::hash::{BuildHasher, Hash};
1313
use core::iter::{Chain, FromIterator};
14-
use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub};
14+
use core::ops::{BitAnd, BitOr, BitXor, Index, RangeBounds, Sub};
1515
use core::slice;
1616

1717
use super::{Entries, Equivalent, IndexMap};
@@ -606,6 +606,46 @@ impl<T, S> IndexSet<T, S> {
606606
}
607607
}
608608

609+
/// Access `IndexSet` values at indexed positions.
610+
///
611+
/// # Examples
612+
///
613+
/// ```
614+
/// use indexmap::IndexSet;
615+
///
616+
/// let mut set = IndexSet::new();
617+
/// for word in "Lorem ipsum dolor sit amet".split_whitespace() {
618+
/// set.insert(word.to_string());
619+
/// }
620+
/// assert_eq!(set[0], "Lorem");
621+
/// assert_eq!(set[1], "ipsum");
622+
/// set.reverse();
623+
/// assert_eq!(set[0], "amet");
624+
/// assert_eq!(set[1], "sit");
625+
/// set.sort();
626+
/// assert_eq!(set[0], "Lorem");
627+
/// assert_eq!(set[1], "amet");
628+
/// ```
629+
///
630+
/// ```should_panic
631+
/// use indexmap::IndexSet;
632+
///
633+
/// let mut set = IndexSet::new();
634+
/// set.insert("foo");
635+
/// println!("{:?}", set[10]); // panics!
636+
/// ```
637+
impl<T, S> Index<usize> for IndexSet<T, S> {
638+
type Output = T;
639+
640+
/// Returns a reference to the value at the supplied `index`.
641+
///
642+
/// ***Panics*** if `index` is out of bounds.
643+
fn index(&self, index: usize) -> &T {
644+
self.get_index(index)
645+
.expect("IndexSet: index out of bounds")
646+
}
647+
}
648+
609649
/// An owning iterator over the items of a `IndexSet`.
610650
///
611651
/// This `struct` is created by the [`into_iter`] method on [`IndexSet`]

tests/quick.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use indexmap::IndexMap;
1+
use indexmap::{IndexMap, IndexSet};
22
use itertools::Itertools;
33

44
use quickcheck::quickcheck;
@@ -163,6 +163,26 @@ quickcheck! {
163163
elements.iter().all(|k| map.get(k).is_some())
164164
}
165165

166+
fn indexing(insert: Vec<u8>) -> bool {
167+
let mut map: IndexMap<_, _> = insert.into_iter().map(|x| (x, x)).collect();
168+
let set: IndexSet<_> = map.keys().cloned().collect();
169+
assert_eq!(map.len(), set.len());
170+
171+
for (i, &key) in set.iter().enumerate() {
172+
assert_eq!(map.get_index(i), Some((&key, &key)));
173+
assert_eq!(set.get_index(i), Some(&key));
174+
assert_eq!(map[i], key);
175+
assert_eq!(set[i], key);
176+
177+
*map.get_index_mut(i).unwrap().1 >>= 1;
178+
map[i] <<= 1;
179+
}
180+
181+
set.iter().enumerate().all(|(i, &key)| {
182+
let value = key & !1;
183+
map[&key] == value && map[i] == value
184+
})
185+
}
166186
}
167187

168188
use crate::Op::*;

0 commit comments

Comments
 (0)