use crate::rules::Rule;
use derivative::Derivative;
use std::{
cell::Cell,
fmt::{Debug, Error, Formatter},
ops::{Deref, Not},
};
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
pub const DEAD: State = State(0);
pub const ALIVE: State = State(1);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct State(pub usize);
impl Not for State {
type Output = State;
fn not(self) -> Self::Output {
match self {
ALIVE => DEAD,
_ => ALIVE,
}
}
}
pub type Coord = (isize, isize, isize);
pub struct LifeCell<'a, 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<'a, R>>,
pub(crate) succ: Option<CellRef<'a, R>>,
pub(crate) nbhd: [Option<CellRef<'a, R>>; 8],
pub(crate) sym: Vec<CellRef<'a, R>>,
pub(crate) is_front: bool,
}
impl<'a, R: Rule> LifeCell<'a, R> {
pub(crate) fn new(coord: Coord, background: State, b0: bool) -> Self {
let succ_state = if b0 { !background } else { background };
LifeCell {
coord,
background,
state: Cell::new(Some(background)),
desc: Cell::new(R::new_desc(background, succ_state)),
pred: Default::default(),
succ: Default::default(),
nbhd: Default::default(),
sym: Default::default(),
is_front: false,
}
}
pub(crate) fn borrow(&self) -> CellRef<'a, R> {
let cell = unsafe { (self as *const LifeCell<'a, R>).as_ref().unwrap() };
CellRef { cell }
}
}
impl<'a, R: Rule<Desc = D>, D: Copy + Debug> Debug for LifeCell<'a, R> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(
f,
"LifeCell {{ coord: {:?}, state: {:?}, desc: {:?} }}",
self.coord,
self.state.get(),
self.desc.get()
)
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub struct CellRef<'a, R: Rule> {
cell: &'a LifeCell<'a, R>,
}
impl<'a, R: Rule> CellRef<'a, R> {
pub(crate) fn update_desc(self, state: Option<State>, new: bool) {
R::update_desc(self, state, new);
}
}
impl<'a, R: Rule> PartialEq for CellRef<'a, R> {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self.cell, other.cell)
}
}
impl<'a, R: Rule> Eq for CellRef<'a, R> {}
impl<'a, R: Rule> Deref for CellRef<'a, R> {
type Target = LifeCell<'a, R>;
fn deref(&self) -> &Self::Target {
self.cell
}
}
impl<'a, R: Rule<Desc = D>, D: Copy + Debug> Debug for CellRef<'a, R> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "CellRef {{ coord: {:?} }}", self.coord)
}
}