use cedar_policy::{Entity, EntityUid};
use smol_str::{SmolStr, ToSmolStr};
use std::collections::{HashMap, hash_map::Entry};
use url::Origin;
type TypeName = SmolStr;
type TypeId = SmolStr;
#[derive(Default)]
pub(crate) struct BuiltEntities {
singles: ahash::HashMap<TypeName, TypeId>,
multiples: ahash::HashMap<TypeName, Vec<TypeId>>,
}
impl FromIterator<EntityUid> for BuiltEntities {
fn from_iter<T: IntoIterator<Item = EntityUid>>(iter: T) -> Self {
iter.into_iter().fold(Self::default(), |mut acc, uid| {
acc.insert(&uid);
acc
})
}
}
impl From<&HashMap<Origin, Entity>> for BuiltEntities {
fn from(src: &HashMap<Origin, Entity>) -> Self {
let mut built_entities = BuiltEntities::default();
for entity in src.values() {
built_entities.insert(&entity.uid());
}
built_entities
}
}
impl BuiltEntities {
pub(crate) fn insert(&mut self, uid: &EntityUid) {
let name = uid.type_name().to_smolstr();
let id = uid.id().escaped();
match self.singles.entry(name.clone()) {
Entry::Occupied(entry) => {
let exsisting_eid = entry.remove();
self.multiples
.entry(name.clone())
.or_default()
.extend([exsisting_eid, id]);
},
Entry::Vacant(entry) => {
entry.insert(id);
},
}
}
pub(crate) fn get_single(&self, type_name: &str) -> Option<&str> {
self.singles.get(type_name).map(|v| &**v)
}
pub(super) fn get_multiple(&self, type_name: &str) -> Option<&[SmolStr]> {
self.multiples.get(type_name).map(|v| &**v)
}
}