Skip to content

Commit

Permalink
Implement indexed types for global properties
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonasher committed Jun 2, 2024
1 parent d62bf0b commit 824b158
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 12 deletions.
37 changes: 25 additions & 12 deletions src/data_containers/heterogeneous_container.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::any::Any;
use std::any::TypeId;
use std::collections::HashMap;
use std::rc::Rc;

use crate::data_containers::Property;

pub struct HeterogeneousContainer {
map: HashMap<TypeId, Rc<dyn Any>>,
data: Vec<Option<Rc<dyn Any>>>,
}

impl Default for HeterogeneousContainer {
Expand All @@ -17,25 +15,34 @@ impl Default for HeterogeneousContainer {

impl HeterogeneousContainer {
pub fn new() -> HeterogeneousContainer {
HeterogeneousContainer {
map: HashMap::new(),
}
HeterogeneousContainer { data: Vec::new() }
}

pub fn set_value<K: Property>(&mut self, value: K::Value) {
self.map.insert(TypeId::of::<K>(), Rc::new(value));
let property_index = K::index();
if property_index >= self.data.len() {
self.data.resize_with(property_index + 1, || None)
}
self.data[property_index] = Some(Rc::new(value));
}

pub fn get_value<K: Property>(&self) -> Option<&K::Value> {
match self.map.get(&TypeId::of::<K>()) {
None => None,
Some(boxed_value) => boxed_value.downcast_ref::<K::Value>(),
let property_index = K::index();
if property_index >= self.data.len() {
return None;
}
self.data[property_index]
.as_ref()
.map(|boxed_value| boxed_value.downcast_ref::<K::Value>().unwrap())
}

pub fn get_rc_value<K: Property>(&self) -> Option<Rc<K::Value>> {
self.map
.get(&TypeId::of::<K>())
let property_index = K::index();
if property_index >= self.data.len() {
return None;
}
self.data[property_index]
.as_ref()
.map(|boxed_value| Rc::clone(boxed_value).downcast::<K::Value>().unwrap())
}
}
Expand All @@ -46,11 +53,17 @@ mod tests {
struct KeyOne {}
impl Property for KeyOne {
type Value = usize;
fn index() -> usize {
0
}
}

struct KeyTwo {}
impl Property for KeyTwo {
type Value = bool;
fn index() -> usize {
1
}
}

#[test]
Expand Down
5 changes: 5 additions & 0 deletions src/data_containers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod vector_person_container;

pub trait Property: Any {
type Value: Any;
fn index() -> usize;
}

pub trait PropertyWithDefault: Any {
Expand All @@ -25,6 +26,10 @@ pub trait PropertyWithDefault: Any {

impl<T: PropertyWithDefault> Property for T {
type Value = T::Value;

fn index() -> usize {
T::index()
}
}

pub trait PersonContainer {
Expand Down
23 changes: 23 additions & 0 deletions src/global_properties.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;

use crate::context::Context;
use crate::data_containers::heterogeneous_container::HeterogeneousContainer;
Expand All @@ -9,13 +11,34 @@ use crate::data_containers::Property;
// TODO: Decide if we want default global property values
pub trait GlobalProperty: Property {}

static INDEX: Mutex<usize> = Mutex::new(0);

pub fn next(index: &AtomicUsize) -> usize {
let mut guard = INDEX.lock().unwrap();
if index.load(Ordering::SeqCst) == usize::MAX {
index.store(*guard, Ordering::SeqCst);
*guard += 1;
}
index.load(Ordering::Relaxed)
}

#[macro_export]
macro_rules! define_global_property {
($global_property:ident, $value:ty) => {
pub struct $global_property {}

impl $crate::data_containers::Property for $global_property {
type Value = $value;

fn index() -> usize {
static INDEX: std::sync::atomic::AtomicUsize =
std::sync::atomic::AtomicUsize::new(usize::MAX);
let mut index = INDEX.load(std::sync::atomic::Ordering::Relaxed);
if index == usize::MAX {
index = $crate::global_properties::next(&INDEX);
}
index
}
}

impl $crate::global_properties::GlobalProperty for $global_property {}
Expand Down

0 comments on commit 824b158

Please sign in to comment.