blob: 468f0a9d8949fc25a07dc2bf11ede825c6866cbb [file] [log] [blame]
#![allow(dead_code)]
use std::borrow::Borrow;
/// Flat (Vec) backed map
///
/// This preserves insertion order
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct FlatMap<K, V> {
keys: Vec<K>,
values: Vec<V>,
}
impl<K: PartialEq + Eq, V> FlatMap<K, V> {
pub(crate) fn new() -> Self {
Default::default()
}
pub(crate) fn insert(&mut self, key: K, mut value: V) -> Option<V> {
for (index, existing) in self.keys.iter().enumerate() {
if *existing == key {
std::mem::swap(&mut self.values[index], &mut value);
return Some(value);
}
}
self.insert_unchecked(key, value);
None
}
pub(crate) fn insert_unchecked(&mut self, key: K, value: V) {
self.keys.push(key);
self.values.push(value);
}
pub(crate) fn extend_unchecked(&mut self, iter: impl IntoIterator<Item = (K, V)>) {
for (key, value) in iter {
self.insert_unchecked(key, value);
}
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Eq,
{
for existing in &self.keys {
if existing.borrow() == key {
return true;
}
}
false
}
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: std::hash::Hash + Eq,
{
self.remove_entry(key).map(|(_, v)| v)
}
pub fn remove_entry<Q: ?Sized>(&mut self, key: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
Q: std::hash::Hash + Eq,
{
let index = some!(self
.keys
.iter()
.enumerate()
.find_map(|(i, k)| (k.borrow() == key).then_some(i)));
let key = self.keys.remove(index);
let value = self.values.remove(index);
Some((key, value))
}
pub(crate) fn is_empty(&self) -> bool {
self.keys.is_empty()
}
pub fn entry(&mut self, key: K) -> Entry<K, V> {
for (index, existing) in self.keys.iter().enumerate() {
if *existing == key {
return Entry::Occupied(OccupiedEntry { v: self, index });
}
}
Entry::Vacant(VacantEntry { v: self, key })
}
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Eq,
{
for (index, existing) in self.keys.iter().enumerate() {
if existing.borrow() == k {
return Some(&self.values[index]);
}
}
None
}
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Eq,
{
for (index, existing) in self.keys.iter().enumerate() {
if existing.borrow() == k {
return Some(&mut self.values[index]);
}
}
None
}
pub fn keys(&self) -> std::slice::Iter<'_, K> {
self.keys.iter()
}
pub fn iter(&self) -> Iter<K, V> {
Iter {
keys: self.keys.iter(),
values: self.values.iter(),
}
}
pub fn iter_mut(&mut self) -> IterMut<K, V> {
IterMut {
keys: self.keys.iter_mut(),
values: self.values.iter_mut(),
}
}
}
impl<K: PartialEq + Eq, V> Default for FlatMap<K, V> {
fn default() -> Self {
Self {
keys: Default::default(),
values: Default::default(),
}
}
}
pub enum Entry<'a, K: 'a, V: 'a> {
Vacant(VacantEntry<'a, K, V>),
Occupied(OccupiedEntry<'a, K, V>),
}
impl<'a, K: 'a, V: 'a> Entry<'a, K, V> {
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(entry) => &mut entry.v.values[entry.index],
Entry::Vacant(entry) => {
entry.v.keys.push(entry.key);
entry.v.values.push(default);
entry.v.values.last_mut().unwrap()
}
}
}
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(entry) => &mut entry.v.values[entry.index],
Entry::Vacant(entry) => {
entry.v.keys.push(entry.key);
entry.v.values.push(default());
entry.v.values.last_mut().unwrap()
}
}
}
}
pub struct VacantEntry<'a, K: 'a, V: 'a> {
v: &'a mut FlatMap<K, V>,
key: K,
}
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
v: &'a mut FlatMap<K, V>,
index: usize,
}
pub struct Iter<'a, K: 'a, V: 'a> {
keys: std::slice::Iter<'a, K>,
values: std::slice::Iter<'a, V>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
match self.keys.next() {
Some(k) => {
let v = self.values.next().unwrap();
Some((k, v))
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.keys.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
match self.keys.next_back() {
Some(k) => {
let v = self.values.next_back().unwrap();
Some((k, v))
}
None => None,
}
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
pub struct IterMut<'a, K: 'a, V: 'a> {
keys: std::slice::IterMut<'a, K>,
values: std::slice::IterMut<'a, V>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
match self.keys.next() {
Some(k) => {
let v = self.values.next().unwrap();
Some((k, v))
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.keys.size_hint()
}
}
impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
match self.keys.next_back() {
Some(k) => {
let v = self.values.next_back().unwrap();
Some((k, v))
}
None => None,
}
}
}
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {}