use alloc::{rc, rc::Rc};
use core::cell::Cell;
use core::fmt;
use core::marker::PhantomData;
mod has_ix;
pub use has_ix::HasIx;
#[repr(C)]
pub struct Ix<T> {
pub(crate) ix: usize,
pub(crate) _t: PhantomData<*mut T>,
#[cfg(feature = "debug-arena")]
pub(crate) nonce: u64,
#[cfg(feature = "debug-arena")]
pub(crate) generation: u64,
}
impl<T> fmt::Debug for Ix<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Ix(")?;
self.ix.fmt(f)?;
#[cfg(feature = "debug-arena")]
{
f.write_str("; ")?;
self.nonce.fmt(f)?;
f.write_str(", ")?;
self.generation.fmt(f)?;
}
f.write_str(")")?;
Ok(())
}
}
impl<T> Clone for Ix<T> {
fn clone(&self) -> Self {
Ix {
ix: self.ix,
_t: PhantomData,
#[cfg(feature = "debug-arena")]
nonce: self.nonce,
#[cfg(feature = "debug-arena")]
generation: self.generation,
}
}
}
impl<T> Copy for Ix<T> {}
unsafe impl<T> Send for Ix<T> {}
unsafe impl<T> Sync for Ix<T> {}
impl<T> PartialEq for Ix<T> {
fn eq(&self, other: &Ix<T>) -> bool {
#[cfg(feature = "debug-arena")]
{
if self.nonce != other.nonce {
panic!("GC: Tested equality for indices into two different regions");
}
if self.generation != other.generation {
panic!("GC: Tested equality for indices in two different generations");
}
}
self.ix == other.ix
}
}
impl<T> Eq for Ix<T> {}
pub(crate) type IxCell<T> = Cell<Ix<T>>;
pub enum SpotVariant<E, T> {
Present(E),
BrokenHeart(Ix<T>),
}
pub struct Weak<T> {
pub(crate) cell: rc::Weak<IxCell<T>>,
}
impl<T> Clone for Weak<T> {
fn clone(&self) -> Self {
Weak {
cell: self.cell.clone(),
}
}
}
impl<T> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Weak(")?;
self.cell.upgrade().map(|c| c.get()).fmt(f)?;
f.write_str(")")?;
Ok(())
}
}
impl<T> PartialEq for Weak<T> {
fn eq(&self, other: &Weak<T>) -> bool {
alloc::rc::Weak::ptr_eq(&self.cell, &other.cell)
}
}
impl<T> Eq for Weak<T> {}
pub struct Root<T> {
pub(crate) cell: Rc<IxCell<T>>,
}
impl<T> Clone for Root<T> {
fn clone(&self) -> Self {
Root {
cell: self.cell.clone(),
}
}
}
impl<T> fmt::Debug for Root<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Root(")?;
self.cell.get().fmt(f)?;
f.write_str(")")?;
Ok(())
}
}
impl<T> PartialEq for Root<T> {
fn eq(&self, other: &Root<T>) -> bool {
alloc::rc::Rc::ptr_eq(&self.cell, &other.cell)
}
}
impl<T> Eq for Root<T> {}
#[derive(Debug, PartialEq, Eq)]
#[allow(unused)]
pub enum Error {
Indeterminable,
IncorrectRegion,
EntryExpired,
UnexpectedInternalState,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self {
Error::Indeterminable => write!(f, "Invalid index"),
Error::IncorrectRegion => write!(f, "Incorrect region for index"),
Error::EntryExpired => write!(f, "Index expired"),
Error::UnexpectedInternalState => write!(f, "Region has invalid internal state"),
}
}
}