pns 0.18.3

A simple and efficient library wrapper for simulating a minimal form of petri nets
Documentation
use std::marker::PhantomData;

/// A node of a petri net; stores the indices to the next and previous nodes.
#[derive(Debug)]
#[repr(C)]
pub struct Node<Id> {
    /// The count of preceding nodes of a node.
    pub prev_count: usize,
    prev_size: usize,
    pub(crate) prev: *mut Id,
    /// The count of following nodes of a node.
    pub next_count: usize,
    next_size: usize,
    pub(crate) next: *mut Id,
}

#[repr(C)]
pub struct IndexList {
    pub(crate) index: usize,
    pub(crate) next: *mut Self,
}

#[derive(Debug)]
#[repr(C)]
pub struct NodeArray {
    pub(crate) count: usize,
    size: usize,
    pub(crate) nodes: *mut Node<usize>,
    pub(crate) reusable: *mut IndexList,
}

/// A type representing a petri net. It only stores the initial state, not the state used for simulation.
#[derive(Debug)]
#[repr(C)]
pub struct Net {
    pub(crate) transitions: NodeArray,
    pub(crate) places: NodeArray,
    pub(crate) initial_token_counts: *mut usize,
}

#[repr(C)]
/// Represents a view of transitions.
/// Can be used as an iterator.
pub struct TransitionView<'a> {
    /// The count of remaining elements.
    pub count: usize,
    pub(crate) transitions: *mut IndexList,
    phantom: PhantomData<&'a mut IndexList>,
}

#[repr(C)]
/// Represents a list of transitions.
/// Can be used as an iterator.
pub struct TransitionList {
    /// The count of remaining elements.
    pub count: usize,
    pub(crate) transitions: *mut IndexList,
}

#[repr(C)]
/// Contains the changes of fireable transitions.
pub struct FireChanges {
    /// A list of recently added transitions.
    pub added: TransitionList,
    /// A list of recently removed transitions.
    pub removed: TransitionList,
}

#[repr(C)]
struct FireInfo {
    count: usize,
    transitions: *mut IndexList,
}

#[repr(C)]
struct FireState {
    active: FireInfo,
    added: FireInfo,
    removed: FireInfo,
}

#[repr(C)]
pub struct CountArray {
    size: usize,
    pub(crate) counts: *mut usize,
}

/// The state of the petri net used for simulation.
///
/// A `State` instance is considered compatible with a `Net` if it was created using that specific `Net`
/// (e.g., by calling `State::new`). For a `State` to be in sync with a `Net`, it must be compatible and
/// the `Net` must not have been edited since the `State` was last refreshed. If the `Net` is modified, you
/// must call the `refresh` method with a compatible `Net` to keep the `State` in sync. Failing to do so
/// may result in most methods being unsafe to call, even if the state is compatible.
#[repr(C)]
pub struct State {
    pub(crate) tokens: CountArray,
    pub(crate) calls: CountArray,
    fire: FireState,
    unfire: FireState,
}