#![allow(clippy::slow_vector_initialization)]
use crate::term::internal::HpoTermInternal;
use crate::HpoTermId;
use tracing::{trace, warn};
use crate::MAX_HPO_ID_INTEGER as HPO_TERM_NUMBERS;
#[derive(Clone)]
pub(super) struct Arena {
terms: Vec<HpoTermInternal>,
ids: Vec<usize>,
}
impl Default for Arena {
fn default() -> Self {
let mut ids = Vec::with_capacity(HPO_TERM_NUMBERS);
ids.resize(HPO_TERM_NUMBERS, 0);
let mut s = Self {
terms: Vec::with_capacity(18_000),
ids,
};
s.terms.push(HpoTermInternal::default());
s
}
}
impl Arena {
pub fn len(&self) -> usize {
self.terms.len() - 1
}
pub fn insert(&mut self, term: HpoTermInternal) {
let id = term.id().to_usize();
if self.ids[id] == 0 {
let idx = self.terms.len();
self.terms.push(term);
self.ids[id] = idx;
}
}
pub fn get(&self, id: HpoTermId) -> Option<&HpoTermInternal> {
match self.ids.get(id.to_usize()) {
Some(0) => {
trace!("Term does not exist in Arena: {}", id);
None
}
Some(n) => Some(&self.terms[*n]),
None => {
warn!("Index of Arena out of bounds for {id}");
None
}
}
}
pub fn get_unchecked(&self, id: HpoTermId) -> &HpoTermInternal {
&self.terms[self.ids[id.to_usize()]]
}
pub fn get_unchecked_mut(&mut self, id: HpoTermId) -> &mut HpoTermInternal {
&mut self.terms[self.ids[id.to_usize()]]
}
pub fn get_mut(&mut self, id: HpoTermId) -> Option<&mut HpoTermInternal> {
match self.ids.get(id.to_usize()) {
Some(0) => None,
Some(n) => Some(&mut self.terms[*n]),
None => {
warn!("Index of Arena out of bounds for {id}");
None
}
}
}
pub fn values(&self) -> &[HpoTermInternal] {
&self.terms[1..]
}
pub fn values_mut(&mut self) -> &mut [HpoTermInternal] {
&mut self.terms[1..]
}
pub fn keys(&mut self) -> Vec<HpoTermId> {
self.terms[1..].iter().map(|term| *term.id()).collect()
}
pub(super) fn iter(&self) -> Iter {
Iter(self.terms[1..].iter().map(|term| *term.id()))
}
}
pub(super) struct Iter<'a>(
std::iter::Map<std::slice::Iter<'a, HpoTermInternal>, fn(&HpoTermInternal) -> HpoTermId>,
);
impl Iterator for Iter<'_> {
type Item = HpoTermId;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}