I tried the change to use RefCell and it was very straightforward, although who knows if it will hold up as you do more operations.
full diff (has some unnecessary changes from the IDE)
diff --git a/libs/hash_collections/src/hash_graph.rs b/libs/hash_collections/src/hash_graph.rs
index a8e1137..7009f91 100644
--- a/libs/hash_collections/src/hash_graph.rs
+++ b/libs/hash_collections/src/hash_graph.rs
@@ -1,6 +1,13 @@
-use std::{hash::{Hash, Hasher}, ops::Index};
-use crate::{hash_map::{FixedSizeHashMapImpl, OutOfCapacityError}, FixedSizeHashMap, FixedSizeHashSet};
+use crate::{
+ FixedSizeHashMap, FixedSizeHashSet,
+ hash_map::{FixedSizeHashMapImpl, OutOfCapacityError},
+};
use std::mem;
+use std::{
+ cell::RefCell,
+ hash::{Hash, Hasher},
+ ops::Index,
+};
use crate::check::{Check, IsTrue, is_prime_and_within_limit};
@@ -21,7 +28,7 @@ where
K: Hash + std::cmp::Eq,
H: Default + Hasher,
{
- _hash_map: FixedSizeHashMapImpl<K, Node<V>, C, H>,
+ _hash_map: FixedSizeHashMapImpl<K, RefCell<Node<V>>, C, H>,
}
impl<'a, K: 'a, V: 'a, const C: usize, H> FixedSizeHashGraphImpl<K, V, C, H>
@@ -30,107 +37,128 @@ where
K: Hash + std::cmp::Eq,
H: Default + Hasher,
{
- fn _insert_or_update_contained_value(&'a mut self, key: K, value: V) -> Result<usize, OutOfCapacityError> {
+ fn _insert_or_update_contained_value(
+ &'a mut self,
+ key: K,
+ value: V,
+ ) -> Result<usize, OutOfCapacityError> {
match self._hash_map._get_mut_value_and_index_of(&key) {
Some((node, index)) => {
- let _ = mem::replace(&mut node._value, value);
- return Result::Ok(index)
+ let _ = mem::replace(&mut node.borrow_mut()._value, value);
+ return Result::Ok(index);
}
None => {
- match self._hash_map._insert_get_index(key, Node {
- _value: value,
- _connected_to: Default::default(),
- _connected_from: Default::default()
- }) {
+ match self._hash_map._insert_get_index(
+ key,
+ RefCell::new(Node {
+ _value: value,
+ _connected_to: Default::default(),
+ _connected_from: Default::default(),
+ }),
+ ) {
Ok((index, _)) => return Ok(index),
- Err(e) => return Err(e)
+ Err(e) => return Err(e),
}
}
}
}
- pub fn insert(&'a mut self, key_value: (K, V), connections: Vec<(K, V)>) -> Result<(), OutOfCapacityError> {
+ pub fn insert(
+ &'a mut self,
+ key_value: (K, V),
+ connections: Vec<(K, V)>,
+ ) -> Result<(), OutOfCapacityError> {
let Ok(index) = self._insert_or_update_contained_value(key_value.0, key_value.1) else {
- return Result::Err(OutOfCapacityError{capacity: self._hash_map.capacity()});
+ return Result::Err(OutOfCapacityError {
+ capacity: self._hash_map.capacity(),
+ });
};
for (to_key, to_value) in connections {
let Ok(to_index) = self._insert_or_update_contained_value(to_key, to_value) else {
- return Result::Err(OutOfCapacityError{capacity: self._hash_map.capacity()});
+ return Result::Err(OutOfCapacityError {
+ capacity: self._hash_map.capacity(),
+ });
};
-
- if index == to_index {continue;}
+
+ if index == to_index {
+ continue;
+ }
if let Some(node) = self._hash_map._get_mut_value_at(index) {
- match node._connected_to.get_mut(&to_index) {
- Some(edge_weight) => {*edge_weight+=1;},
- None => {let _ = node._connected_to.insert(to_index, 1);}
+ match node.borrow_mut()._connected_to.get_mut(&to_index) {
+ Some(edge_weight) => {
+ *edge_weight += 1;
+ }
+ None => {
+ let _ = node.borrow_mut()._connected_to.insert(to_index, 1);
+ }
}
}
-
+
if let Some(to_node) = self._hash_map._get_mut_value_at(to_index) {
- let _ = to_node._connected_from.insert(index, ());
+ let _ = to_node.borrow_mut()._connected_from.insert(index, ());
}
}
- return Ok(())
+ return Ok(());
}
fn connect_to(&mut self, k: &K, to_keys: Vec<&K>) {
let Some(index) = self._hash_map._get_index_of(k) else {
- return
+ return;
};
-
+
for to_key in to_keys {
let Some(to_index) = self._hash_map._get_index_of(to_key) else {
continue;
};
if index != to_index {
if let Some(node) = self._hash_map._get_mut_value_at(index) {
- let _ = node._connected_to.insert_or(to_index, 1, |weight| *weight+=1);
+ let _ = node
+ .borrow_mut()
+ ._connected_to
+ .insert_or(to_index, 1, |weight| *weight += 1);
}
if let Some(to_node) = self._hash_map._get_mut_value_at(to_index) {
- let _ = to_node._connected_from.insert(index, ());
+ let _ = to_node.borrow_mut()._connected_from.insert(index, ());
}
}
}
}
fn remove(&mut self, key: &K) {
- let (index, to_indexes, from_indexes): (usize, Vec<usize>, Vec<usize>) =
- match self._hash_map._get_mut_value_and_index_of(key) {
- Some((node, index)) => {
- (
- index,
- node._connected_to.iter_head().map(|kv| *kv.0).collect(),
- node._connected_from.iter_head().map(|kv| *kv.0).collect()
- )
- },
- None => return,
- };
-
- for to_index in to_indexes {
- let Some(to_node) = self._hash_map._get_mut_value_at(to_index) else {
+ // mut borrow occurs on node being removed vvvvvvvvvvvvvv
+ let Some((node, index)) = self._hash_map._get_val_and_index_of(key) else {
+ return;
+ };
+
+ // remove all the connections/edges
+ for (to_index, _) in node.borrow()._connected_to.iter_head() {
+ // mut borrow occurs on connected_to nodes vvvvvvvvvvvvvv [E0499]
+ let Some(to_node) = self._hash_map._get_value_at(*to_index) else {
continue;
};
- to_node._connected_from.remove(&index);
+ to_node.borrow_mut()._connected_from.remove(&index);
}
- for from_index in from_indexes {
- let Some(from_node) = self._hash_map._get_mut_value_at(from_index) else {
+ for (from_index, _) in node.borrow()._connected_from.iter_head() {
+ // mut borrow occurs on connected_from nodes vvvvvvvvvvvvvv [E0499]
+ let Some(from_node) = self._hash_map._get_value_at(*from_index) else {
continue;
};
- from_node._connected_to.remove(&index);
+ from_node.borrow_mut()._connected_to.remove(&index);
}
- self._hash_map.remove(&key);
+ // finally remove the node
+ self._hash_map.remove(key);
}
// fn disconnect_from(&mut self, key: &K, to_keys: Vec<&K>) {
// let Some((node, index)) = self._hash_map._get_mut_and_index(key) else {
// return
// };
-
+
// for to_key in to_keys {
// let Some((to_node, to_index)) = self._hash_map._get_mut_and_index(to_key) else {
// continue;
@@ -150,4 +178,4 @@ where
// fn disconnect_all() {
// }
-}
\ No newline at end of file
+}
diff --git a/libs/hash_collections/src/hash_map.rs b/libs/hash_collections/src/hash_map.rs
index 9152b7b..14a5f3e 100644
--- a/libs/hash_collections/src/hash_map.rs
+++ b/libs/hash_collections/src/hash_map.rs
@@ -1,18 +1,24 @@
+use std::error;
+use std::fmt;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Index, IndexMut};
-use std::error;
-use std::fmt;
use crate::check::{Check, IsTrue, is_prime_and_within_limit};
#[derive(Debug, Clone, PartialEq)]
-pub struct OutOfCapacityError {pub capacity: usize}
+pub struct OutOfCapacityError {
+ pub capacity: usize,
+}
impl fmt::Display for OutOfCapacityError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "HashMap has reached its capacity of {} entries", self.capacity)
+ write!(
+ f,
+ "HashMap has reached its capacity of {} entries",
+ self.capacity
+ )
}
}
@@ -69,8 +75,6 @@ where
_phantom: PhantomData<H>,
}
-
-
impl<K, V, const C: usize, H> Default for FixedSizeHashMapImpl<K, V, C, H>
where
Check<{ is_prime_and_within_limit(C, 25013) }>: IsTrue,
@@ -103,10 +107,16 @@ where
map
}
- pub(crate) fn _insert_get_index(&mut self, key: K, value: V) -> Result<(usize, Option<V>), OutOfCapacityError> {
+ pub(crate) fn _insert_get_index(
+ &mut self,
+ key: K,
+ value: V,
+ ) -> Result<(usize, Option<V>), OutOfCapacityError> {
let i = self._find_index(&key, false);
if i == Self::CAPACITY {
- return Result::Err(OutOfCapacityError{capacity: Self::CAPACITY});
+ return Result::Err(OutOfCapacityError {
+ capacity: Self::CAPACITY,
+ });
}
let mut old_val: Option<V> = None;
@@ -136,7 +146,12 @@ where
result.map(|rv| rv.1)
}
- pub fn insert_or<F: FnOnce(&mut V)>(&mut self, key: K, value: V, op: F) -> Result<(), OutOfCapacityError> {
+ pub fn insert_or<F: FnOnce(&mut V)>(
+ &mut self,
+ key: K,
+ value: V,
+ op: F,
+ ) -> Result<(), OutOfCapacityError> {
if let Some(value) = self.get_mut(&key) {
op(value);
Ok(())
@@ -147,13 +162,14 @@ where
pub fn exists(&self, key: &K) -> bool {
let i = self._find_index(key, true);
- i != Self::CAPACITY && self._data[i].is_occupied()
+ i != Self::CAPACITY && self._data[i].is_occupied()
}
pub fn get(&self, key: &K) -> Option<&V> {
let i = self._find_index(key, true);
- if i != Self::CAPACITY && let Slot::IsOccupiedBy(ref entry) = self._data[i]
+ if i != Self::CAPACITY
+ && let Slot::IsOccupiedBy(ref entry) = self._data[i]
{
Some(&entry.value)
} else {
@@ -164,7 +180,8 @@ where
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
let i = self._find_index(key, true);
- if i < Self::CAPACITY && let Slot::IsOccupiedBy(ref mut entry) = self._data[i]
+ if i < Self::CAPACITY
+ && let Slot::IsOccupiedBy(ref mut entry) = self._data[i]
{
Some(&mut entry.value)
} else {
@@ -174,13 +191,19 @@ where
pub(crate) fn _get_index_of(&mut self, key: &K) -> Option<usize> {
let i = self._find_index(key, true);
- if i != Self::CAPACITY && self._data[i].is_occupied() {Some(i)} else {None}
+ if i != Self::CAPACITY && self._data[i].is_occupied() {
+ Some(i)
+ } else {
+ None
+ }
}
pub(crate) fn _get_mut_value_and_index_of(&mut self, key: &K) -> Option<(&mut V, usize)> {
let i = self._find_index(key, true);
- if i != Self::CAPACITY && let Slot::IsOccupiedBy(ref mut entry) = self._data[i] {
- Some ((&mut entry.value, i))
+ if i != Self::CAPACITY
+ && let Slot::IsOccupiedBy(ref mut entry) = self._data[i]
+ {
+ Some((&mut entry.value, i))
} else {
None
}
@@ -188,8 +211,10 @@ where
pub(crate) fn _get_val_and_index_of(&self, key: &K) -> Option<(&V, usize)> {
let i = self._find_index(key, true);
- if i != Self::CAPACITY && let Slot::IsOccupiedBy(ref entry) = self._data[i] {
- Some ((&entry.value, i))
+ if i != Self::CAPACITY
+ && let Slot::IsOccupiedBy(ref entry) = self._data[i]
+ {
+ Some((&entry.value, i))
} else {
None
}
@@ -231,7 +256,9 @@ where
self._get_key_val_at(self._tail)
}
- pub fn iter_head(&self) -> MapIterator<'_, K, V, C, impl Fn(&Entry<K, V, C>) -> usize + use<K, V, C, H>> {
+ pub fn iter_head(
+ &self,
+ ) -> MapIterator<'_, K, V, C, impl Fn(&Entry<K, V, C>) -> usize + use<K, V, C, H>> {
MapIterator {
_remaining: self._size,
_current: self._head,
@@ -240,7 +267,9 @@ where
}
}
- pub fn iter_tail(&self) -> MapIterator<'_, K, V, C, impl Fn(&Entry<K, V, C>) -> usize + use<K, V, C, H>> {
+ pub fn iter_tail(
+ &self,
+ ) -> MapIterator<'_, K, V, C, impl Fn(&Entry<K, V, C>) -> usize + use<K, V, C, H>> {
MapIterator {
_remaining: self._size,
_current: self._tail,
@@ -338,8 +367,18 @@ where
}
}
+ pub(crate) fn _get_value_at(&self, i: usize) -> Option<&V> {
+ if i < Self::CAPACITY
+ && let Slot::IsOccupiedBy(ref entry) = self._data[i]
+ {
+ Some(&entry.value)
+ } else {
+ None
+ }
+ }
+
pub(crate) fn _get_mut_value_at(&mut self, i: usize) -> Option<&mut V> {
- if i < Self::CAPACITY
+ if i < Self::CAPACITY
&& let Slot::IsOccupiedBy(ref mut entry) = self._data[i]
{
Some(&mut entry.value)