hyperast 0.2.0

Temporal code analyses at scale
Documentation
use super::*;
use hashbrown::hash_map::DefaultHashBuilder;
use hecs::{Entity, EntityRef as EntryRef, World};

pub struct PendingInsert<'a>(
    crate::compat::hash_map::RawEntryMut<'a, Entity, (), ()>,
    (u64, &'a mut World, &'a DefaultHashBuilder),
);

impl<'a> PendingInsert<'a> {
    pub fn occupied_id(&self) -> Option<NodeIdentifier> {
        match &self.0 {
            hashbrown::hash_map::RawEntryMut::Occupied(occupied) => Some(occupied.key().clone()),
            _ => None,
        }
    }
    pub fn resolve<T>(&self, id: NodeIdentifier) -> HashedNodeRef<T> {
        self.1 .1.entity(id).map(|x| HashedNodeRef::new(x)).unwrap()
    }
    pub fn occupied(
        &'a self,
    ) -> Option<(NodeIdentifier, (u64, &'a World, &'a DefaultHashBuilder))> {
        match &self.0 {
            hashbrown::hash_map::RawEntryMut::Occupied(occupied) => {
                Some((occupied.key().clone(), (self.1 .0, self.1 .1, self.1 .2)))
            }
            _ => None,
        }
    }

    pub fn vacant(
        self,
    ) -> (
        crate::compat::hash_map::RawVacantEntryMut<'a, Entity, (), ()>,
        (u64, &'a mut World, &'a DefaultHashBuilder),
    ) {
        match self.0 {
            hashbrown::hash_map::RawEntryMut::Vacant(occupied) => (occupied, self.1),
            _ => panic!(),
        }
    }
}

impl NodeStore {
    pub fn prepare_insertion<'a, Eq: Fn(EntryRef) -> bool, V: std::hash::Hash>(
        &'a mut self,
        hashable: &'a V,
        eq: Eq,
    ) -> PendingInsert {
        let Self {
            dedup,
            internal: backend,
            ..
        } = self;
        let hash = crate::utils::make_hash(&self.hasher, hashable);
        let entry = dedup.raw_entry_mut().from_hash(hash, |symbol| {
            let r = eq(backend.entity(*symbol).unwrap());
            r
        });
        PendingInsert(entry, (hash, &mut self.internal, &self.hasher))
    }

    pub fn insert_after_prepare<T>(
        (vacant, (hash, internal, hasher)): (
            crate::compat::hash_map::RawVacantEntryMut<Entity, (), ()>,
            (u64, &mut World, &DefaultHashBuilder),
        ),
        components: T,
    ) -> Entity
    where
        T: hecs::DynamicBundle,
    {
        let (&mut symbol, _) = {
            let symbol = internal.spawn(components);
            vacant.insert_with_hasher(hash, symbol, (), |id| {
                let node: elem::HashedNodeRef<'_, NodeIdentifier> =
                    internal.entity(*id).map(|x| HashedNodeRef::new(x)).unwrap();

                crate::utils::make_hash(hasher, &node)
            })
        };
        symbol
    }
}