aboutsummaryrefslogtreecommitdiff
path: root/src/utils/vec_map.rs
diff options
context:
space:
mode:
authoracdenisSK <[email protected]>2018-01-02 18:34:27 +0100
committeracdenisSK <[email protected]>2018-01-02 18:34:27 +0100
commit26fe139363a847542bbe609fe4d15accbf4fef14 (patch)
treee0f0bbcb1d70b9905235366e86c21acac49dadd9 /src/utils/vec_map.rs
parentRemove builder re-export in utils (diff)
downloadserenity-26fe139363a847542bbe609fe4d15accbf4fef14.tar.xz
serenity-26fe139363a847542bbe609fe4d15accbf4fef14.zip
Move `VecMap` to `utils`
This also fixes no-builder compilation
Diffstat (limited to 'src/utils/vec_map.rs')
-rw-r--r--src/utils/vec_map.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/utils/vec_map.rs b/src/utils/vec_map.rs
new file mode 100644
index 0000000..786bf14
--- /dev/null
+++ b/src/utils/vec_map.rs
@@ -0,0 +1,120 @@
+// Most of this is
+// shamelessly copied from https://github.com/hyperium/hyper/blob/master/src/header/internals/vec_map.rs
+
+/// Like `HashMap` but solely uses a vector instead.
+///
+/// note: This is for internal use.
+#[derive(Clone, Debug, Default)]
+pub struct VecMap<K, V>(Vec<(K, V)>);
+
+impl<K: PartialEq, V> VecMap<K, V> {
+ pub fn new() -> Self {
+ VecMap(Vec::new())
+ }
+
+ pub fn with_capacity(cap: usize) -> Self {
+ VecMap(Vec::with_capacity(cap))
+ }
+
+ #[inline]
+ pub fn insert(&mut self, key: K, value: V) {
+ self.0.push((key, value));
+ }
+
+ pub fn remove<Q: ?Sized + PartialEq<K>>(&mut self, key: &Q) -> Option<V> {
+ self.pos(key).map(|pos| self.0.remove(pos)).map(|entry| entry.1)
+ }
+
+ pub fn entry(&mut self, key: K) -> Entry<K, V> {
+ match self.pos(&key) {
+ Some(pos) => Entry::Occupied(OccupiedEntry {
+ vec: &mut self.0,
+ pos: pos,
+ }),
+ None => Entry::Vacant(VacantEntry {
+ vec: &mut self.0,
+ key: key,
+ })
+ }
+ }
+
+ pub fn get<Q: PartialEq<K> + ?Sized>(&self, key: &Q) -> Option<&V> {
+ self.iter().find(|entry| key == &entry.0).map(|entry| &entry.1)
+ }
+
+ #[inline]
+ pub fn iter(&self) -> ::std::slice::Iter<(K, V)> {
+ self.into_iter()
+ }
+
+ fn pos<Q: PartialEq<K> + ?Sized>(&self, key: &Q) -> Option<usize> {
+ self.iter().position(|entry| key == &entry.0)
+ }
+}
+
+impl<K, V> IntoIterator for VecMap<K, V> {
+ type Item = (K, V);
+ type IntoIter = ::std::vec::IntoIter<(K, V)>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.0.into_iter()
+ }
+}
+
+impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
+ type Item = &'a (K, V);
+ type IntoIter = ::std::slice::Iter<'a, (K, V)>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.0.iter()
+ }
+}
+
+pub enum Entry<'a, K: 'a, V: 'a> {
+ Vacant(VacantEntry<'a, K, V>),
+ Occupied(OccupiedEntry<'a, K, V>)
+}
+
+impl<'a, K, V> Entry<'a, K, V> {
+ pub fn or_insert(self, val: V) -> &'a mut V {
+ use self::Entry::*;
+
+ match self {
+ Vacant(entry) => entry.insert(val),
+ Occupied(entry) => entry.into_mut(),
+ }
+ }
+
+ pub fn or_insert_with<F: FnOnce() -> V>(self, val: F) -> &'a mut V {
+ use self::Entry::*;
+
+ match self {
+ Vacant(entry) => entry.insert(val()),
+ Occupied(entry) => entry.into_mut(),
+ }
+ }
+}
+
+pub struct VacantEntry<'a, K: 'a, V: 'a> {
+ vec: &'a mut Vec<(K, V)>,
+ key: K,
+}
+
+impl<'a, K, V> VacantEntry<'a, K, V> {
+ pub fn insert(self, val: V) -> &'a mut V {
+ self.vec.push((self.key, val));
+ let pos = self.vec.len() - 1;
+ &mut self.vec[pos].1
+ }
+}
+
+pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
+ vec: &'a mut Vec<(K, V)>,
+ pos: usize,
+}
+
+impl<'a, K, V> OccupiedEntry<'a, K, V> {
+ pub fn into_mut(self) -> &'a mut V {
+ &mut self.vec[self.pos].1
+ }
+} \ No newline at end of file