use std::{
any::{Any, TypeId},
collections::HashMap,
};
#[derive(Default)]
pub struct Blackboard {
properties: HashMap<String, Box<dyn Any + Send + Sync>>,
}
impl std::fmt::Debug for Blackboard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Blackboard")
.field("properties", &self.properties.keys().collect::<Vec<_>>())
.finish()
}
}
impl Blackboard {
pub fn len(&self) -> usize {
self.properties.len()
}
pub fn is_empty(&self) -> bool {
self.properties.is_empty()
}
pub fn has_property(&self, name: &str) -> bool {
self.properties.contains_key(name)
}
pub fn has_property_of_type<T>(&self, name: &str) -> bool
where
T: 'static,
{
if let Some(value) = self.properties.get(name) {
return value.is::<T>();
}
false
}
pub fn type_id(&self, name: &str) -> Option<TypeId> {
if let Some(value) = self.properties.get(name) {
let v: &dyn Any = value;
return Some(v.type_id());
}
None
}
pub fn get<T>(&self, name: &str) -> Option<&T>
where
T: 'static,
{
if let Some(value) = self.properties.get(name) {
return value.downcast_ref();
}
None
}
pub fn get_mut<T>(&mut self, name: &str) -> Option<&mut T>
where
T: 'static,
{
if let Some(value) = self.properties.get_mut(name) {
return value.downcast_mut();
}
None
}
pub fn raw(&self, name: &str) -> Option<&dyn Any> {
if let Some(value) = self.properties.get(name) {
return Some(value);
}
None
}
pub fn raw_mut(&mut self, name: &str) -> Option<&mut dyn Any> {
if let Some(value) = self.properties.get_mut(name) {
return Some(&mut *value);
}
None
}
pub fn set<T>(&mut self, name: String, value: T)
where
T: Any + 'static + Send + Sync,
{
self.properties.insert(name, Box::new(value));
}
pub fn set_raw(&mut self, name: String, value: Box<dyn Any + Send + Sync>) {
self.properties.insert(name, value);
}
pub fn with<T, R, F>(&mut self, name: &str, mut f: F) -> Option<R>
where
F: FnMut(&mut T) -> R,
T: 'static,
{
if let Some(value) = self.properties.get_mut(name)
&& let Some(value) = value.downcast_mut()
{
return Some(f(value));
}
None
}
pub fn remove(&mut self, name: &str) -> bool {
self.properties.remove(name).is_some()
}
pub fn clear(&mut self) {
self.properties.clear();
}
pub fn keys(&self) -> impl Iterator<Item = &str> {
self.properties.keys().map(|k| k.as_str())
}
pub fn key_types(&self) -> impl Iterator<Item = (&str, TypeId)> {
self.properties.iter().map(|(k, v)| {
let v: &dyn Any = v;
(k.as_str(), v.type_id())
})
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &dyn Any)> {
self.properties.iter().map(|(k, v)| {
let v: &dyn Any = v;
(k.as_str(), v)
})
}
}