summaryrefslogtreecommitdiff
path: root/platforms/tortuise-script-compiled/src/entity.rs
blob: 507690d1cfeaadd73c2b425cbb6e67597b448235 (plain)
use core::ops::{Deref, DerefMut};

use spin::lock_api::{MappedRwLockWriteGuard, RwLock, RwLockWriteGuard};

use crate::ScriptContext;

pub struct Entity<T> {
	data: RwLock<Option<T>>,
	default: fn(&ScriptContext) -> T,
}

pub struct EntityRef<'entity, T> {
	data: MappedRwLockWriteGuard<'entity, T>,
}

pub struct EntityMut<'entity, T> {
	data: MappedRwLockWriteGuard<'entity, T>,
}

impl<T> Entity<T> {
	pub const fn new(_name: &'static str, default: fn(&ScriptContext) -> T) -> Self {
		Self {
			data: RwLock::new(None),
			default,
		}
	}

	pub const fn from_string(name: String, default: fn(&ScriptContext) -> T) -> Self {
		core::mem::forget(name);
		Self {
			data: RwLock::new(None),
			default,
		}
	}

	pub fn get(&self, context: &ScriptContext) -> EntityRef<'_, T> {
		puffin::profile_function!();
		let data = RwLockWriteGuard::map(self.data.write(), |data| {
			data.get_or_insert_with(|| (self.default)(context))
		});
		EntityRef { data }
	}

	pub fn get_mut(&self, context: &ScriptContext) -> EntityMut<'_, T> {
		puffin::profile_function!();
		let data = RwLockWriteGuard::map(self.data.write(), |data| {
			data.get_or_insert_with(|| (self.default)(context))
		});
		EntityMut { data }
	}
}

impl<T> Deref for EntityRef<'_, T> {
	type Target = T;

	fn deref(&self) -> &Self::Target {
		&self.data
	}
}

impl<T> Deref for EntityMut<'_, T> {
	type Target = T;

	fn deref(&self) -> &Self::Target {
		&self.data
	}
}

impl<T> DerefMut for EntityMut<'_, T> {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.data
	}
}