use std::borrow::Borrow;
use crate::ported::hashtab::{hash_hash, hashtab_T, Slot};
impl<V> hashtab_T<V> {
pub fn len(&self) -> usize {
self.ht_used
}
pub fn is_empty(&self) -> bool {
self.ht_used == 0
}
pub fn clear(&mut self) {
*self = Self::default();
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
Q: AsRef<str> + ?Sized,
String: Borrow<Q>,
{
let key = key.as_ref();
let (idx, found) = self.hash_lookup(key, hash_hash(key));
match &self.ht_array[idx] {
Slot::Used { value, .. } if found => Some(value),
_ => None,
}
}
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
Q: AsRef<str> + ?Sized,
String: Borrow<Q>,
{
let key = key.as_ref();
let (idx, found) = self.hash_lookup(key, hash_hash(key));
match &mut self.ht_array[idx] {
Slot::Used { value, .. } if found => Some(value),
_ => None,
}
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
Q: AsRef<str> + ?Sized,
String: Borrow<Q>,
{
let key = key.as_ref();
self.hash_lookup(key, hash_hash(key)).1
}
pub fn insert(&mut self, key: String, value: V) -> Option<V> {
let h = hash_hash(&key);
let (idx, found) = self.hash_lookup(&key, h);
if found {
let Slot::Used { value: slot, .. } = &mut self.ht_array[idx] else {
unreachable!("hash_lookup reported a hit on a non-item slot");
};
return Some(std::mem::replace(slot, value));
}
self.hash_add_item(idx, key, h, value);
None
}
pub fn shift_remove<Q>(&mut self, key: &Q) -> Option<V>
where
Q: AsRef<str> + ?Sized,
String: Borrow<Q>,
{
let key = key.as_ref();
let (idx, found) = self.hash_lookup(key, hash_hash(key));
if !found {
return None;
}
self.hash_remove(idx)
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &V)> {
self.ht_array.iter().filter_map(|s| match s {
Slot::Used { key, value, .. } => Some((key, value)),
_ => None,
})
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&String, &mut V)> {
self.ht_array.iter_mut().filter_map(|s| match s {
Slot::Used { key, value, .. } => Some((&*key, value)),
_ => None,
})
}
pub fn get_index(&self, n: usize) -> Option<(&String, &V)> {
self.iter().nth(n)
}
pub fn keys(&self) -> impl Iterator<Item = &String> {
self.iter().map(|(k, _)| k)
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.iter().map(|(_, v)| v)
}
}
impl<'a, V> IntoIterator for &'a hashtab_T<V> {
type Item = (&'a String, &'a V);
type IntoIter = Box<dyn Iterator<Item = (&'a String, &'a V)> + 'a>;
fn into_iter(self) -> Self::IntoIter {
Box::new(self.iter())
}
}
impl<V> FromIterator<(String, V)> for hashtab_T<V> {
fn from_iter<I: IntoIterator<Item = (String, V)>>(iter: I) -> Self {
let mut ht = Self::default();
for (k, v) in iter {
ht.insert(k, v);
}
ht
}
}