use std::{
collections::{hash_map::RandomState, HashMap},
hash::BuildHasher,
sync::Arc,
};
use zakura_chain::transparent::{OrderedUtxo, OutPoint};
#[cfg(test)]
mod tests;
const PARTITIONS: usize = 256;
type OutputMap = HashMap<OutPoint, Arc<OrderedUtxo>>;
#[derive(Clone, Debug)]
pub(crate) struct CreatedUtxos {
hash: RandomState,
partitions: Vec<Arc<OutputMap>>,
len: usize,
}
impl Default for CreatedUtxos {
fn default() -> Self {
Self {
hash: RandomState::new(),
partitions: (0..PARTITIONS).map(|_| Arc::new(HashMap::new())).collect(),
len: 0,
}
}
}
impl CreatedUtxos {
fn partition(&self, key: &OutPoint) -> usize {
let mask = u64::try_from(PARTITIONS - 1).expect("the partition count fits in u64");
usize::try_from(self.hash.hash_one(key) & mask).expect("a partition index fits in usize")
}
pub(crate) fn get(&self, key: &OutPoint) -> Option<&Arc<OrderedUtxo>> {
self.partitions[self.partition(key)].get(key)
}
pub(crate) fn insert(
&mut self,
key: OutPoint,
value: Arc<OrderedUtxo>,
) -> Option<Arc<OrderedUtxo>> {
let partition = self.partition(&key);
let previous = Arc::make_mut(&mut self.partitions[partition]).insert(key, value);
if previous.is_none() {
self.len += 1;
}
previous
}
pub(crate) fn remove(&mut self, key: &OutPoint) -> Option<Arc<OrderedUtxo>> {
let partition = self.partition(key);
let removed = Arc::make_mut(&mut self.partitions[partition]).remove(key);
if removed.is_some() {
self.len -= 1;
}
removed
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (&OutPoint, &Arc<OrderedUtxo>)> {
self.partitions
.iter()
.flat_map(|partition| partition.iter())
}
#[cfg(test)]
pub(crate) fn contains_key(&self, key: &OutPoint) -> bool {
self.get(key).is_some()
}
}
impl PartialEq for CreatedUtxos {
fn eq(&self, other: &Self) -> bool {
self.len == other.len
&& self
.iter()
.all(|(key, value)| other.get(key) == Some(value))
}
}
impl Eq for CreatedUtxos {}
#[cfg(test)]
impl std::ops::Index<&OutPoint> for CreatedUtxos {
type Output = Arc<OrderedUtxo>;
fn index(&self, key: &OutPoint) -> &Self::Output {
self.get(key)
.expect("indexed outpoints were inserted by the test")
}
}