use crate::rules::Rule;
use educe::Educe;
use std::{
cell::Cell,
fmt::{Debug, Error, Formatter},
ops::{Deref, Not},
ptr::NonNull,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct State(pub usize);
pub const DEAD: State = State(0);
pub const ALIVE: State = State(1);
impl Not for State {
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
match self {
ALIVE => DEAD,
_ => ALIVE,
}
}
}
pub type Coord = (i32, i32, i32);
pub struct LifeCell<R: Rule> {
pub coord: Coord,
pub(crate) background: State,
pub(crate) state: Cell<Option<State>>,
pub(crate) desc: Cell<R::Desc>,
pub(crate) pred: Option<CellRef<R>>,
pub(crate) succ: Option<CellRef<R>>,
pub(crate) nbhd: [Option<CellRef<R>>; 8],
pub(crate) sym: Vec<CellRef<R>>,
pub(crate) next: Option<CellRef<R>>,
pub(crate) is_front: bool,
pub(crate) level: Cell<u32>,
pub(crate) seen: Cell<bool>,
}
impl<R: Rule> LifeCell<R> {
#[inline]
pub(crate) fn new(coord: Coord, background: State, succ_state: State) -> Self {
Self {
coord,
background,
state: Cell::new(Some(background)),
desc: Cell::new(R::new_desc(background, succ_state)),
pred: None,
succ: None,
nbhd: [None; 8],
sym: Vec::new(),
next: None,
is_front: false,
level: Cell::new(0),
seen: Cell::new(false),
}
}
#[inline]
pub(crate) fn update_desc(&self, state: State, new: bool) {
R::update_desc(self, state, new);
}
}
impl<R: Rule<Desc = D>, D: Copy + Debug> Debug for LifeCell<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.debug_struct("LifeCell")
.field("coord", &self.coord)
.field("state", &self.state.get())
.field("desc", &self.desc.get())
.field("is_front", &self.is_front)
.finish()
}
}
#[repr(transparent)]
#[derive(Educe)]
#[educe(Clone, Copy, PartialEq, Eq, Hash)]
pub struct CellRef<R: Rule> {
cell: NonNull<LifeCell<R>>,
}
impl<R: Rule> CellRef<R> {
#[inline]
pub(crate) const unsafe fn new(ptr: *mut LifeCell<R>) -> Self {
Self {
cell: NonNull::new_unchecked(ptr),
}
}
}
impl<R: Rule> Deref for CellRef<R> {
type Target = LifeCell<R>;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { self.cell.as_ref() }
}
}
impl<R: Rule> Debug for CellRef<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.debug_struct("CellRef")
.field("coord", &self.coord)
.finish()
}
}