use crate::CapacityError;
use core::mem::swap;
#[derive(Clone, Debug, Hash)]
pub struct PetitMap<K, V, const CAP: usize> {
pub(crate) storage: [Option<(K, V)>; CAP],
}
impl<K, V, const CAP: usize> Default for PetitMap<K, V, CAP> {
fn default() -> Self {
Self::new()
}
}
impl<K, V, const CAP: usize> PetitMap<K, V, CAP> {
pub fn new() -> Self {
PetitMap {
storage: [(); CAP].map(|_| None),
}
}
pub fn get_at(&self, index: usize) -> Option<(&K, &V)> {
assert!(index <= CAP);
if let Some((key, value)) = &self.storage[index] {
Some((key, value))
} else {
None
}
}
pub fn get_at_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> {
assert!(index <= CAP);
if let Some((key, value)) = &mut self.storage[index] {
Some((key, value))
} else {
None
}
}
pub fn remove_at(&mut self, index: usize) -> bool {
self.take_at(index).is_some()
}
#[must_use = "Use remove_at if the value is not needed."]
pub fn take_at(&mut self, index: usize) -> Option<(K, V)> {
assert!(index <= CAP);
if let Some((_key, _value)) = &self.storage[index] {
let mut removed = None;
swap(&mut removed, &mut self.storage[index]);
removed
} else {
None
}
}
pub fn iter(&self) -> impl Iterator<Item = &(K, V)> {
self.storage.iter().filter_map(|e| e.as_ref())
}
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.iter().map(|(k, _v)| k)
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.iter().map(|(_k, v)| v)
}
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.storage
.iter_mut()
.filter_map(|e| e.as_mut())
.map(|(_k, v)| v)
}
pub fn next_filled_index(&self, cursor: usize) -> Option<usize> {
if cursor >= CAP {
return None;
}
for i in cursor..CAP {
if self.storage[i].is_some() {
return Some(i);
}
}
None
}
pub fn next_empty_index(&self, cursor: usize) -> Option<usize> {
if cursor >= CAP {
return None;
}
for i in cursor..CAP {
if self.storage[i].is_none() {
return Some(i);
}
}
None
}
pub fn len(&self) -> usize {
self.storage.iter().filter(|e| e.is_some()).count()
}
pub const fn capacity(&self) -> usize {
CAP
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn is_full(&self) -> bool {
self.len() == CAP
}
pub fn swap_at(&mut self, index_a: usize, index_b: usize) {
assert!(index_a <= CAP);
assert!(index_b <= CAP);
self.storage.swap(index_a, index_b);
}
pub fn clear(&mut self) {
for index in 0..CAP {
self.storage[index] = None;
}
}
pub fn insert_unchecked(&mut self, key: K, value: V) -> Option<usize> {
let index = self.next_empty_index(0)?;
self.storage[index] = Some((key, value));
Some(index)
}
}
impl<K: Eq, V, const CAP: usize> PetitMap<K, V, CAP> {
pub fn try_insert(
&mut self,
key: K,
mut value: V,
) -> Result<SuccesfulMapInsertion<V>, CapacityError<(K, V)>> {
if let Some(index) = self.find(&key) {
let (_key, old_value) = self.get_at_mut(index).unwrap();
swap(&mut value, old_value);
Ok(SuccesfulMapInsertion::ExtantKey(value, index))
} else if let Some(index) = self.next_empty_index(0) {
self.storage[index] = Some((key, value));
Ok(SuccesfulMapInsertion::NovelKey(index))
} else {
Err(CapacityError((key, value)))
}
}
pub fn insert(&mut self, key: K, value: V) -> SuccesfulMapInsertion<V> {
self.try_insert(key, value)
.expect("Inserting this key-value pair would have overflowed the map!")
}
pub fn insert_at(&mut self, key: K, value: V, index: usize) -> Option<(K, V)> {
assert!(index <= CAP);
if let Some(old_index) = self.find(&key) {
self.swap_at(old_index, index);
None
} else if self.get_at(index).is_some() {
let removed = self.take_at(index);
self.storage[index] = Some((key, value));
removed
} else {
self.storage[index] = Some((key, value));
None
}
}
pub fn find(&self, key: &K) -> Option<usize> {
for index in 0..CAP {
if let Some((existing_key, _val)) = &self.storage[index] {
if *key == *existing_key {
return Some(index);
}
}
}
None
}
pub fn contains_key(&self, key: &K) -> bool {
self.find(key).is_some()
}
pub fn get(&self, key: &K) -> Option<&V> {
if let Some(index) = self.find(key) {
if let Some((_key, value)) = &self.storage[index] {
return Some(value);
}
}
None
}
pub fn get_key_value(&self, key: &K) -> Option<(&K, &V)> {
if let Some(index) = self.find(key) {
if let Some((key, value)) = &self.storage[index] {
return Some((key, value));
}
}
None
}
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
if let Some(index) = self.find(key) {
if let Some((_key, value)) = &mut self.storage[index] {
return Some(value);
}
}
None
}
pub fn remove(&mut self, key: &K) -> Option<usize> {
if let Some(index) = self.find(key) {
self.remove_at(index);
Some(index)
} else {
None
}
}
#[must_use = "Use remove if the value is not needed."]
pub fn take(&mut self, key: &K) -> Option<(usize, (K, V))> {
if let Some(index) = self.find(key) {
let result = self.take_at(index).map(|pair| (index, pair));
debug_assert!(result.is_some());
result
} else {
None
}
}
pub fn swap(&mut self, key_a: &K, key_b: &K) -> bool {
if let (Some(index_a), Some(index_b)) = (self.find(key_a), self.find(key_b)) {
self.swap_at(index_a, index_b);
true
} else {
false
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&K, &mut V) -> bool,
{
for i in 0..self.capacity() {
if let Some((k, v)) = self.get_at_mut(i) {
if f(k, v) {
self.remove_at(i);
}
}
}
}
pub fn try_from_iter<I: IntoIterator<Item = (K, V)>>(
element_iter: I,
) -> Result<Self, CapacityError<(Self, (K, V))>> {
let mut map = Self::new();
for (k, v) in element_iter {
if let Err(CapacityError(overfull_element)) = map.try_insert(k, v) {
return Err(CapacityError((map, overfull_element)));
}
}
Ok(map)
}
pub fn from_raw_array_unchecked(values: [Option<(K, V)>; CAP]) -> Self {
Self { storage: values }
}
}
impl<K: Eq, V, const CAP: usize> Extend<(K, V)> for PetitMap<K, V, CAP> {
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
for (key, value) in iter {
self.insert(key, value);
}
}
}
impl<K: Eq, V: PartialEq, const CAP: usize> PetitMap<K, V, CAP> {
pub fn identical(&self, other: Self) -> bool {
for i in 0..CAP {
if self.storage[i] != other.storage[i] {
return false;
}
}
true
}
}
impl<K: Eq, V, const CAP: usize> FromIterator<(K, V)> for PetitMap<K, V, CAP> {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
PetitMap::try_from_iter(iter).unwrap()
}
}
impl<K: Eq, V, const CAP: usize> IntoIterator for PetitMap<K, V, CAP> {
type Item = (K, V);
type IntoIter = PetitMapIter<K, V, CAP>;
fn into_iter(self) -> Self::IntoIter {
PetitMapIter {
map: self,
cursor: 0,
}
}
}
#[derive(Clone, Debug)]
pub struct PetitMapIter<K: Eq, V, const CAP: usize> {
map: PetitMap<K, V, CAP>,
cursor: usize,
}
impl<K: Eq, V, const CAP: usize> PetitMapIter<K, V, CAP> {
#[must_use]
pub fn into_map(self) -> PetitMap<K, V, CAP> {
self.map
}
}
impl<K: Eq, V, const CAP: usize> Iterator for PetitMapIter<K, V, CAP> {
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
if let Some(index) = self.map.next_filled_index(self.cursor) {
self.cursor = index + 1;
self.map.take_at(index)
} else {
self.cursor = CAP;
None
}
}
}
impl<K: Eq, V: PartialEq, const CAP: usize, const OTHER_CAP: usize>
PartialEq<PetitMap<K, V, OTHER_CAP>> for PetitMap<K, V, CAP>
{
fn eq(&self, other: &PetitMap<K, V, OTHER_CAP>) -> bool {
for key in self.keys() {
if self.get(key) != other.get(key) {
return false;
}
}
true
}
}
impl<K: Eq, V: Eq, const CAP: usize> Eq for PetitMap<K, V, CAP> {}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SuccesfulMapInsertion<V> {
NovelKey(usize),
ExtantKey(V, usize),
}