use super::List;
use crate::alloc::collections::btree_map;
pub enum Map<'a, K: Ord, V> {
Pairs(List<'a, (K, V)>),
Btree(btree_map::BTreeMap<K, V>),
}
pub enum Entry<'map, 'a, K: Ord, V> {
Occupied(OccupiedEntry<'map, 'a, K, V>),
Vacant(VacantEntry<'map, 'a, K, V>),
Full,
}
pub struct OccupiedEntry<'map, 'a, K: Ord, V> {
inner: Occupied<'map, 'a, K, V>,
}
enum Occupied<'map, 'a, K, V> {
Pairs {
list: &'map mut List<'a, (K, V)>,
index: usize,
key: K,
},
Btree(btree_map::OccupiedEntry<'map, K, V>),
}
pub struct VacantEntry<'map, 'a, K: Ord, V> {
inner: Vacant<'map, 'a, K, V>,
}
enum Vacant<'map, 'a, K, V> {
Pairs {
list: &'map mut List<'a, (K, V)>,
key: K,
},
Btree(btree_map::VacantEntry<'map, K, V>),
}
impl<K: Ord, V> Map<'_, K, V> {
pub fn get(&self, key: &K) -> Option<&V> {
match self {
Map::Pairs(list) => list
.as_slice()
.iter()
.find(|(k, _)| k == key)
.map(|(_, val)| val),
Map::Btree(tree) => tree.get(key),
}
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
match self {
Map::Pairs(list) => list
.as_mut_slice()
.iter_mut()
.find(|(k, _)| k == key)
.map(|(_, val)| val),
Map::Btree(tree) => tree.get_mut(key),
}
}
}
impl<'a, K: Ord, V> Map<'a, K, V> {
pub fn entry(&mut self, key: K) -> Entry<'_, 'a, K, V> {
match self {
Map::Pairs(list) => {
let index = list
.as_slice()
.iter()
.position(|(k, _)| k == &key);
match index {
Some(index) => Entry::Occupied(OccupiedEntry {
inner: Occupied::Pairs {
list,
index,
key,
},
}),
None if list.len() == list.capacity() => Entry::Full,
None => Entry::Vacant(VacantEntry {
inner: Vacant::Pairs {
list,
key,
},
}),
}
},
Map::Btree(tree) => tree.entry(key).into(),
}
}
}
impl<'map, 'a, K: Ord, V> Entry<'map, 'a, K, V> {
pub fn occupied(self) -> Option<OccupiedEntry<'map, 'a, K, V>> {
match self {
Entry::Occupied(occ) => Some(occ),
_ => None,
}
}
pub fn vacant(self) -> Option<VacantEntry<'map, 'a, K, V>> {
match self {
Entry::Vacant(vac) => Some(vac),
_ => None,
}
}
pub fn remove(self) {
if let Some(occupied) = self.occupied() {
occupied.remove()
}
}
}
impl<'map, K: Ord, V> OccupiedEntry<'map, '_, K, V> {
pub fn get(&self) -> &V {
match &self.inner {
Occupied::Pairs { list, index, .. } => &list[*index].1,
Occupied::Btree(btree) => btree.get(),
}
}
pub fn get_mut(&mut self) -> &mut V {
match &mut self.inner {
Occupied::Pairs { list, index, .. } => &mut list[*index].1,
Occupied::Btree(btree) => btree.get_mut(),
}
}
pub fn into_mut(self) -> &'map mut V {
match self.inner {
Occupied::Pairs { list, index, .. } => &mut list[index].1,
Occupied::Btree(btree) => btree.into_mut(),
}
}
pub fn remove(self) {
match self.inner {
Occupied::Pairs { list, index, .. } => { list.remove_at(index).expect("Element was present"); },
Occupied::Btree(btree) => { btree.remove_entry(); },
}
}
pub fn remove_key(self) -> K {
match self.inner {
Occupied::Pairs { list, index, key } => { list.remove_at(index).expect("Element was present"); key },
Occupied::Btree(btree) => btree.remove_entry().0,
}
}
}
impl<'map, K: Ord, V> VacantEntry<'map, '_, K, V> {
pub fn into_key(self) -> K {
match self.inner {
Vacant::Pairs { key, .. } => key,
Vacant::Btree(btree) => btree.into_key(),
}
}
pub fn insert(self, value: V) -> &'map mut V {
match self.inner {
Vacant::Pairs { list, key } => {
let empty = list.push()
.expect("List was not full");
*empty = (key, value);
&mut empty.1
},
Vacant::Btree(btree) => btree.insert(value),
}
}
}
impl<'a, K: Ord, V>
From<btree_map::Entry<'a, K, V>>
for Entry<'a, '_, K, V> {
fn from(entry: btree_map::Entry<'a, K, V>) -> Self {
match entry {
btree_map::Entry::Occupied(occ) => Entry::Occupied(OccupiedEntry {
inner: Occupied::Btree(occ),
}),
btree_map::Entry::Vacant(vac) => Entry::Vacant(VacantEntry {
inner: Vacant::Btree(vac),
}),
}
}
}