pub use crate::entry::{Entry, OccupiedEntry, VacantEntry};
use crate::{
cell::CellStack,
compaction::{Compactor, NullCompactor},
digits::Digits,
node::Node,
Cell,
};
use std::{cmp::PartialEq, iter::FromIterator};
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HexTreeMap<V, C = NullCompactor> {
pub(crate) nodes: Box<[Option<Box<Node<V>>>]>,
compactor: C,
}
impl<V> HexTreeMap<V, NullCompactor> {
pub fn new() -> Self {
Self {
nodes: std::iter::repeat_with(|| None)
.take(122)
.collect::<Box<[Option<Box<Node<V>>>]>>(),
compactor: NullCompactor,
}
}
}
impl<V, C: Compactor<V>> HexTreeMap<V, C> {
pub fn insert(&mut self, cell: Cell, value: V) {
let base_cell = cell.base();
let digits = Digits::new(cell);
match self.nodes[base_cell as usize].as_mut() {
Some(node) => node.insert(cell, 0_u8, digits, value, &mut self.compactor),
None => {
let mut node = Box::new(Node::new());
node.insert(cell, 0_u8, digits, value, &mut self.compactor);
self.nodes[base_cell as usize] = Some(node);
}
}
}
}
impl<V, C> HexTreeMap<V, C> {
pub fn with_compactor(compactor: C) -> Self {
Self {
nodes: std::iter::repeat_with(|| None)
.take(122)
.collect::<Box<[Option<Box<Node<V>>>]>>(),
compactor,
}
}
pub fn replace_compactor<NewC>(self, new_compactor: NewC) -> HexTreeMap<V, NewC> {
HexTreeMap {
nodes: self.nodes,
compactor: new_compactor,
}
}
pub fn len(&self) -> usize {
self.nodes.iter().flatten().map(|node| node.len()).sum()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn contains(&self, cell: Cell) -> bool {
let base_cell = cell.base();
match self.nodes[base_cell as usize].as_ref() {
Some(node) => {
let digits = Digits::new(cell);
node.contains(digits)
}
None => false,
}
}
#[inline]
pub fn get(&self, cell: Cell) -> Option<(Cell, &V)> {
match self.get_raw(cell) {
Some((cell, Node::Leaf(val))) => Some((cell, val)),
_ => None,
}
}
#[inline]
pub(crate) fn get_raw(&self, cell: Cell) -> Option<(Cell, &Node<V>)> {
let base_cell = cell.base();
match self.nodes[base_cell as usize].as_ref() {
Some(node) => {
let digits = Digits::new(cell);
node.get(0, cell, digits)
}
None => None,
}
}
#[inline]
pub fn get_mut(&mut self, cell: Cell) -> Option<(Cell, &mut V)> {
match self.get_raw_mut(cell) {
Some((cell, &mut Node::Leaf(ref mut val))) => Some((cell, val)),
_ => None,
}
}
#[inline]
pub(crate) fn get_raw_mut(&mut self, cell: Cell) -> Option<(Cell, &mut Node<V>)> {
let base_cell = cell.base();
match self.nodes[base_cell as usize].as_mut() {
Some(node) => {
let digits = Digits::new(cell);
node.get_mut(0, cell, digits)
}
None => None,
}
}
pub fn entry(&'_ mut self, cell: Cell) -> Entry<'_, V, C> {
if self.get(cell).is_none() {
return Entry::Vacant(VacantEntry {
target_cell: cell,
map: self,
});
}
Entry::Occupied(OccupiedEntry {
target_cell: cell,
cell_value: self.get_mut(cell).unwrap(),
})
}
pub fn iter(&self) -> impl Iterator<Item = (Cell, &V)> {
crate::iteration::Iter::new(&self.nodes, CellStack::new())
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (Cell, &mut V)> {
crate::iteration::IterMut::new(&mut self.nodes, CellStack::new())
}
pub fn subtree_iter(&self, cell: Cell) -> impl Iterator<Item = (Cell, &V)> {
let base_cell = cell.base();
match self.nodes[base_cell as usize].as_ref() {
Some(node) => {
let digits = Digits::new(cell);
match node.get(0, cell, digits) {
Some((cell, Node::Leaf(val))) => Some((cell, val))
.into_iter()
.chain(crate::iteration::Iter::empty()),
Some((cell, Node::Parent(children))) => None
.into_iter()
.chain(crate::iteration::Iter::new(children, CellStack::from(cell))),
None => None.into_iter().chain(crate::iteration::Iter::empty()),
}
}
None => None.into_iter().chain(crate::iteration::Iter::empty()),
}
}
pub fn subtree_iter_mut(&mut self, cell: Cell) -> impl Iterator<Item = (Cell, &mut V)> {
let base_cell = cell.base();
match self.nodes[base_cell as usize].as_mut() {
Some(node) => {
let digits = Digits::new(cell);
match node.get_mut(0, cell, digits) {
Some((cell, Node::Leaf(val))) => Some((cell, val))
.into_iter()
.chain(crate::iteration::IterMut::empty()),
Some((cell, Node::Parent(children))) => None.into_iter().chain(
crate::iteration::IterMut::new(children, CellStack::from(cell)),
),
None => None.into_iter().chain(crate::iteration::IterMut::empty()),
}
}
None => None.into_iter().chain(crate::iteration::IterMut::empty()),
}
}
}
impl<V: PartialEq> Default for HexTreeMap<V, NullCompactor> {
fn default() -> Self {
HexTreeMap::new()
}
}
impl<V> FromIterator<(Cell, V)> for HexTreeMap<V, NullCompactor> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (Cell, V)>,
{
let mut map = HexTreeMap::new();
for (cell, value) in iter {
map.insert(cell, value);
}
map
}
}
impl<'a, V: Copy + 'a> FromIterator<(&'a Cell, &'a V)> for HexTreeMap<V, NullCompactor> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (&'a Cell, &'a V)>,
{
let mut map = HexTreeMap::new();
for (cell, value) in iter {
map.insert(*cell, *value);
}
map
}
}
impl<V, C: Compactor<V>> Extend<(Cell, V)> for HexTreeMap<V, C> {
fn extend<I: IntoIterator<Item = (Cell, V)>>(&mut self, iter: I) {
for (cell, val) in iter {
self.insert(cell, val)
}
}
}
impl<'a, V: Copy + 'a, C: Compactor<V>> Extend<(&'a Cell, &'a V)> for HexTreeMap<V, C> {
fn extend<I: IntoIterator<Item = (&'a Cell, &'a V)>>(&mut self, iter: I) {
for (cell, val) in iter {
self.insert(*cell, *val)
}
}
}
impl<V, C> std::ops::Index<Cell> for HexTreeMap<V, C> {
type Output = V;
fn index(&self, cell: Cell) -> &V {
self.get(cell).expect("no entry found for cell").1
}
}
impl<V, C> std::ops::Index<&Cell> for HexTreeMap<V, C> {
type Output = V;
fn index(&self, cell: &Cell) -> &V {
self.get(*cell).expect("no entry found for cell").1
}
}
impl<V, C> std::ops::IndexMut<Cell> for HexTreeMap<V, C> {
fn index_mut(&mut self, cell: Cell) -> &mut V {
self.get_mut(cell).expect("no entry found for cell").1
}
}
impl<V, C> std::ops::IndexMut<&Cell> for HexTreeMap<V, C> {
fn index_mut(&mut self, cell: &Cell) -> &mut V {
self.get_mut(*cell).expect("no entry found for cell").1
}
}
impl<V: std::fmt::Debug, C> std::fmt::Debug for HexTreeMap<V, C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("{")?;
let mut iter = self.iter();
if let Some((cell, val)) = iter.next() {
write!(f, "{cell:?}: {val:?}")?
}
for (cell, val) in iter {
write!(f, ", {cell:?}: {val:?}")?
}
f.write_str("}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn map_is_send() {
fn assert_send<T: Send>() {}
assert_send::<HexTreeMap<i32>>();
}
#[test]
fn map_is_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<HexTreeMap<i32>>();
}
}