use alloc::sync::Arc;
#[macro_export(local_inner_macros)]
macro_rules! storage_id_type {
($name:ident) => {
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
pub struct $name {
value: usize,
}
impl $name {
pub fn new() -> Self {
use core::sync::atomic::{AtomicUsize, Ordering};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let value = COUNTER.fetch_add(1, Ordering::Relaxed);
if value == usize::MAX {
core::panic!("Memory ID overflowed");
}
Self { value }
}
}
impl Default for $name {
fn default() -> Self {
Self::new()
}
}
};
}
#[derive(Clone, Debug)]
pub struct HandleRef<Id> {
id: Arc<Id>,
all: Arc<()>,
}
#[derive(Clone, Debug)]
pub struct BindingRef<Id> {
id: Id,
_all: Arc<()>,
}
impl<Id> BindingRef<Id>
where
Id: Clone + core::fmt::Debug,
{
pub(crate) fn id(&self) -> &Id {
&self.id
}
}
impl<Id> HandleRef<Id>
where
Id: Clone + core::fmt::Debug,
{
pub(crate) fn new(id: Id) -> Self {
Self {
id: Arc::new(id),
all: Arc::new(()),
}
}
pub(crate) fn id(&self) -> &Id {
&self.id
}
pub(crate) fn binding(self) -> BindingRef<Id> {
BindingRef {
id: self.id.as_ref().clone(),
_all: self.all,
}
}
pub(crate) fn can_mut(&self) -> bool {
Arc::strong_count(&self.id) <= 2
}
pub(crate) fn is_free(&self) -> bool {
Arc::strong_count(&self.all) <= 1
}
}
#[macro_export(local_inner_macros)]
macro_rules! memory_id_type {
($id:ident, $handle:ident) => {
#[derive(Clone, Debug)]
pub struct $handle {
value: $crate::id::HandleRef<$id>,
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub struct $id {
pub(crate) value: usize,
}
impl $handle {
pub(crate) fn new() -> Self {
let value = Self::gen_id();
Self {
value: $crate::id::HandleRef::new($id { value }),
}
}
fn gen_id() -> usize {
static COUNTER: core::sync::atomic::AtomicUsize =
core::sync::atomic::AtomicUsize::new(0);
let value = COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
if value == usize::MAX {
core::panic!("Memory ID overflowed");
}
value
}
}
impl core::ops::Deref for $handle {
type Target = $crate::id::HandleRef<$id>;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl Default for $handle {
fn default() -> Self {
Self::new()
}
}
};
($id:ident, $handle:ident, $binding:ident) => {
memory_id_type!($id, $handle);
#[derive(Clone, Debug)]
pub struct $binding {
value: $crate::id::BindingRef<$id>,
}
impl $handle {
pub(crate) fn binding(self) -> $binding {
$binding {
value: self.value.binding(),
}
}
}
impl core::ops::Deref for $binding {
type Target = $crate::id::BindingRef<$id>;
fn deref(&self) -> &Self::Target {
&self.value
}
}
};
}