use std::{
borrow::Cow,
collections::{HashMap, HashSet},
ops::{Index, IndexMut}
};
use crate::object::{Context, Object, ObjectRef};
pub struct Tree
{
enabled: HashSet<ObjectRef>,
by_class: HashMap<String, Vec<ObjectRef>>,
by_id: HashSet<ObjectRef>,
count: usize
}
impl Tree
{
pub fn is_enabled(&self, obj: ObjectRef) -> bool
{
return self.enabled.contains(&obj);
}
pub fn exists(&self, obj: ObjectRef) -> bool
{
return self.by_id.contains(&obj);
}
pub fn get_count(&self) -> usize
{
return self.count;
}
pub fn get_all(&self) -> impl Iterator<Item = &ObjectRef>
{
return self.enabled.iter();
}
pub fn get_all_ignore_enable(&self) -> impl Iterator<Item = &ObjectRef>
{
return self.by_id.iter();
}
pub fn find_by_class(&self, class: &str) -> Cow<'_, [ObjectRef]>
{
if let Some(v) = self.by_class.get(class) {
return Cow::from(v);
}
return Cow::from(Vec::new());
}
pub(crate) fn insert(&mut self, obj: ObjectRef, class: &str)
{
self.by_id.insert(obj);
let var = self
.by_class
.entry(String::from(class))
.or_insert_with(Vec::new);
var.push(obj);
self.count += 1;
}
pub(crate) fn remove(&mut self, obj: ObjectRef, class: &str)
{
self.by_id.remove(&obj);
self.enabled.remove(&obj);
if let Some(v) = self.by_class.get_mut(class) {
v.retain(|s| *s != obj);
}
self.count -= 1;
}
pub(crate) fn set_enabled(&mut self, obj: ObjectRef, enabled: bool) {
if enabled {
self.enabled.insert(obj);
} else {
self.enabled.remove(&obj);
}
}
pub(crate) fn new() -> Tree
{
return Tree {
enabled: HashSet::new(),
by_class: HashMap::new(),
by_id: HashSet::new(),
count: 0
};
}
}
pub struct Storage<C: Context>
{
objects: Vec<Option<Box<dyn Object<C>>>>
}
impl<C: Context> Storage<C>
{
pub fn new() -> Storage<C>
{
Storage { objects: Vec::new() }
}
pub fn insert<F: FnOnce(ObjectRef) -> Box<dyn Object<C>>>(
&mut self,
func: F
) -> (ObjectRef, &mut Box<dyn Object<C>>)
{
let empty_slot = {
let mut id = 0;
while id < self.objects.len() && self.objects[id].is_some() {
id += 1;
}
if id == self.objects.len() {
None
} else {
Some(id)
}
};
let obj_ref;
if let Some(slot) = empty_slot {
obj_ref = slot as ObjectRef;
self.objects[slot] = Some(func(obj_ref));
} else {
let id = self.objects.len() as ObjectRef;
obj_ref = id;
self.objects.push(Some(func(obj_ref)));
}
let o = unsafe { self.objects[obj_ref as usize].as_mut().unwrap_unchecked() };
return (obj_ref, o);
}
pub fn destroy(&mut self, obj: ObjectRef) {
self.objects[obj as usize] = None;
}
pub fn objects(&mut self) -> impl Iterator<Item = &mut Option<Box<dyn Object<C>>>>
{
return self.objects.iter_mut();
}
}
impl<C: Context> Index<ObjectRef> for Storage<C>
{
type Output = Box<dyn Object<C>>;
fn index(&self, index: ObjectRef) -> &Self::Output
{
return self.objects[index as usize].as_ref().unwrap();
}
}
impl<C: Context> IndexMut<ObjectRef> for Storage<C>
{
fn index_mut(&mut self, index: ObjectRef) -> &mut Self::Output
{
return self.objects[index as usize].as_mut().unwrap();
}
}