diff options
| author | acdenisSK <[email protected]> | 2018-01-02 18:34:27 +0100 |
|---|---|---|
| committer | acdenisSK <[email protected]> | 2018-01-02 18:34:27 +0100 |
| commit | 26fe139363a847542bbe609fe4d15accbf4fef14 (patch) | |
| tree | e0f0bbcb1d70b9905235366e86c21acac49dadd9 /src/utils/vec_map.rs | |
| parent | Remove builder re-export in utils (diff) | |
| download | serenity-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.rs | 120 |
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 |