diff --git a/stackline/src/context.rs b/stackline/src/context.rs index ff3156d..ecc796f 100644 --- a/stackline/src/context.rs +++ b/stackline/src/context.rs @@ -2,16 +2,57 @@ use std::marker::PhantomData; use std::rc::Rc; use super::*; -/// An UpdateContext is created for every tile update during the "update" phase, -/// and it contains the necessary data for a tile to update its internal state. -/// -/// During the update phase, a tile may only access itself mutably, through the mutable -/// reference it was initially passed through its [`update`](Tile::update) method. -/// All accesses to other tiles and all signals must be done immutably. -/// -/// It thus *cannot* access itself through this context structure, although it may read its -/// signal here. -/// It *can* access the other tiles and their signals immutably. +/** An `UpdateContext` is created for every tile update during the "update" phase, +and it contains the necessary data for a tile to update its internal state. + +During the update phase, a tile may only access itself mutably, through the mutable +reference it was initially passed through its [`update`](Tile::update) method. +All accesses to other tiles and all signals must be done immutably. + +It thus *cannot* access itself through this context structure, although it may read its +signal here. +It *can* access the other tiles and their signals immutably. + +## Examples + +This type is most commonly found when implementing [`Tile::update`]: + +``` +# use stackline::{*, tile::Tile, utils::State, context::*}; +# +#[derive(Clone, Debug)] +struct MyTile(u8); + +impl Tile for MyTile { + fn update<'b>(&'b mut self, ctx: UpdateContext<'b>) { + // Counts the number of active neighbors + let mut active_neighbors = 0; + + for dy in -1..1 { + for dx in -1..1 { + let offset = (dx, dy); + if offset == (0, 0) { + continue; + } + + // Get tile next to us: + if let Some((_position, tile)) = ctx.get_offset(offset) { + if tile.state() == State::Active { + active_neighbors += 1; + } + } + } + } + + self.0 = active_neighbors; + ctx.next_state(); // Go dormant + } +# +# fn transmit<'b>(&'b self, signal: std::rc::Rc, ctx: TransmitContext<'b>) {} +} +``` + +**/ // SAFETY: `pane[position].cell` is borrow mutably, while a pointer to the original Pane is kept; // thus, no other reference to `pane[position].cell` may be done @@ -24,6 +65,7 @@ pub struct UpdateContext<'a> { } impl<'a> UpdateContext<'a> { + /// Creates a new context, returning the only mutable reference to `pane[position].cell` and the `UpdateContext`. #[inline] pub(crate) fn new(pane: &'a mut Pane, position: (usize, usize)) -> Option<(Self, &'a mut AnyTile)> { @@ -40,11 +82,13 @@ impl<'a> UpdateContext<'a> { Some((res, tile.as_mut()?)) } + /// Returns the position of the currently updated tile. #[inline] pub fn position(&self) -> (usize, usize) { self.position } + /// Returns the [signal](crate::FullTile::signal) of the currently updated tile. #[inline] pub fn signal<'b>(&'b self) -> Option<&'b Rc> where 'a: 'b { let pane = unsafe { self.pane() }; @@ -53,16 +97,19 @@ impl<'a> UpdateContext<'a> { pane.get(self.position).unwrap().signal() } + /// Returns the state of the current tile. #[inline] pub fn state(&self) -> State { *self.state } + /// Sets the state of the current tile to `state`. #[inline] pub fn set_state(&mut self, state: State) { *self.state = state; } + /// Sets the state of the current tile to `state.next()` #[inline] pub fn next_state(&mut self) { *self.state = self.state.next(); @@ -110,8 +157,8 @@ impl<'a> UpdateContext<'a> { /// and it contains the necessary data for a tile to transmit its internal signal to other tiles. /// /// During this phase, the tile may access itself through an immutable borrow and its signal through an owned reference. -/// It may access the other tiles immutably, but it cannot access the other signals. -/// It can read and modify any tile's state. +/// It *can* access the other tiles immutably, but it *cannot* access the other signals. +/// It *can* read and modify any tile's state. // SAFETY: this structures ensures that it has exlusive, mutable access to `∀x, pane[x].signal, pane[x].state` and `pane.signals`. // Other parts of `pane` may be accessed and returned immutably. @@ -141,6 +188,7 @@ impl<'a> TransmitContext<'a> { Some((res, tile, signal)) } + /// Returns the position of the current tile #[inline] pub fn position(&self) -> (usize, usize) { self.position diff --git a/stackline/src/tile/mod.rs b/stackline/src/tile/mod.rs index 86f5da4..17ac71b 100644 --- a/stackline/src/tile/mod.rs +++ b/stackline/src/tile/mod.rs @@ -130,7 +130,7 @@ pub trait Tile: DynClone + std::fmt::Debug { /// Should return true iff the tile accepts a signal travelling in `Direction` #[inline] - fn accepts_signal(&self, _direction: Direction) -> bool { + fn accepts_signal(&self, direction: Direction) -> bool { true } } diff --git a/stackline/src/utils.rs b/stackline/src/utils.rs index 9b36060..a723887 100644 --- a/stackline/src/utils.rs +++ b/stackline/src/utils.rs @@ -1,4 +1,5 @@ -/// Represents one or many undirected orientation(s), since we are in a 2D grid, this may either be [Horizontal], [Vertical] or both ([Any]) +/// Represents one or many undirected orientation(s), since we are in a 2D grid, +/// this may either be [Horizontal](Orientation::Horizontal), [Vertical](Orientation::Vertical) or both ([Any](Orientation::Any)) #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] pub enum Orientation { @@ -18,7 +19,7 @@ pub enum Direction { } /// Represents the state that a cell may be in. The usual state transition schema is `Idle → Active → Dormant → Idle`. -/// A tile will only be [`update`d](Tile::update) if it is in the `Active` or `Dormant` state. +/// A tile will only be [`update`d](crate::Tile::update) if it is in the `Active` or `Dormant` state. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] pub enum State { @@ -62,7 +63,7 @@ impl Orientation { } impl Direction { - /// Converts a [Direction] in a pair `(Δx, Δy)`, with [Up] being equal to `(0, -1)` + /// Converts a [Direction] in a pair `(Δx, Δy)`, with [Up](Direction::Up) being equal to `(0, -1)` #[inline] pub fn into_offset(self) -> (i8, i8) { match self {