pub mod validate;
#[cfg(any(test, feature = "bench"))]
pub mod bench;
use crate::node::Node;
use crate::prelude::{MemoryManager, PlatformClock, Telemetry};
use crate::{
edge::{link::EdgeDescriptor, Edge, EdgeOccupancy},
errors::{GraphError, NodeError},
graph::validate::{GraphDescBuf, GraphValidator},
message::payload::Payload,
node::{link::NodeDescriptor, StepContext, StepResult},
policy::{EdgePolicy, NodePolicy},
};
pub trait GraphNodeAccess<const I: usize> {
type Node;
fn node_ref(&self) -> &Self::Node;
fn node_mut(&mut self) -> &mut Self::Node;
}
pub trait GraphEdgeAccess<const E: usize> {
type Edge;
fn edge_ref(&self) -> &Self::Edge;
fn edge_mut(&mut self) -> &mut Self::Edge;
}
pub trait GraphNodeTypes<const I: usize, const IN: usize, const OUT: usize> {
type InP: Payload;
type OutP: Payload;
type InQ: Edge;
type OutQ: Edge;
type InM: MemoryManager<Self::InP>;
type OutM: MemoryManager<Self::OutP>;
}
pub trait GraphNodeContextBuilder<const I: usize, const IN: usize, const OUT: usize>:
GraphNodeTypes<I, IN, OUT>
{
#[allow(clippy::type_complexity)]
fn make_step_context<'graph, 'telemetry, 'clock, C, T>(
&'graph mut self,
clock: &'clock C,
telemetry: &'telemetry mut T,
) -> StepContext<
'graph,
'telemetry,
'clock,
IN,
OUT,
<Self as GraphNodeTypes<I, IN, OUT>>::InP,
<Self as GraphNodeTypes<I, IN, OUT>>::OutP,
<Self as GraphNodeTypes<I, IN, OUT>>::InQ,
<Self as GraphNodeTypes<I, IN, OUT>>::OutQ,
<Self as GraphNodeTypes<I, IN, OUT>>::InM,
<Self as GraphNodeTypes<I, IN, OUT>>::OutM,
C,
T,
>
where
EdgePolicy: Copy,
C: PlatformClock + Sized,
T: Telemetry + Sized;
fn with_node_and_step_context<'telemetry, 'clock, C, T, R, E>(
&mut self,
clock: &'clock C,
telemetry: &'telemetry mut T,
f: impl FnOnce(
&mut <Self as GraphNodeAccess<I>>::Node,
&mut StepContext<
'_,
'telemetry,
'clock,
IN,
OUT,
<Self as GraphNodeTypes<I, IN, OUT>>::InP,
<Self as GraphNodeTypes<I, IN, OUT>>::OutP,
<Self as GraphNodeTypes<I, IN, OUT>>::InQ,
<Self as GraphNodeTypes<I, IN, OUT>>::OutQ,
<Self as GraphNodeTypes<I, IN, OUT>>::InM,
<Self as GraphNodeTypes<I, IN, OUT>>::OutM,
C,
T,
>,
) -> Result<R, E>,
) -> Result<R, E>
where
Self: GraphNodeAccess<I>,
EdgePolicy: Copy,
C: PlatformClock + Sized,
T: Telemetry + Sized;
}
pub trait GraphApi<const NODE_COUNT: usize, const EDGE_COUNT: usize> {
fn get_node_descriptors(&self) -> [NodeDescriptor; NODE_COUNT];
fn get_edge_descriptors(&self) -> [EdgeDescriptor; EDGE_COUNT];
fn get_node_policies(&self) -> [NodePolicy; NODE_COUNT];
fn get_edge_policies(&self) -> [EdgePolicy; EDGE_COUNT];
#[inline]
fn validate_graph(&self) -> Result<(), GraphError> {
GraphDescBuf::new(self.get_node_descriptors(), self.get_edge_descriptors()).validate()
}
fn edge_occupancy_for<const E: usize>(&self) -> Result<EdgeOccupancy, GraphError>;
fn write_all_edge_occupancies(
&self,
out: &mut [EdgeOccupancy; EDGE_COUNT],
) -> Result<(), GraphError>;
fn refresh_occupancies_for_node<const I: usize, const IN: usize, const OUT: usize>(
&self,
out: &mut [EdgeOccupancy; EDGE_COUNT],
) -> Result<(), GraphError>;
fn step_node_by_index<C, T>(
&mut self,
index: usize,
clock: &C,
telemetry: &mut T,
) -> Result<StepResult, NodeError>
where
EdgePolicy: Copy,
C: PlatformClock + Sized,
T: Telemetry + Sized;
fn node_policy_for<const I: usize, const IN: usize, const OUT: usize>(&self) -> NodePolicy
where
Self: GraphNodeAccess<I> + GraphNodeTypes<I, IN, OUT>,
<Self as GraphNodeAccess<I>>::Node: Node<
IN,
OUT,
<Self as GraphNodeTypes<I, IN, OUT>>::InP,
<Self as GraphNodeTypes<I, IN, OUT>>::OutP,
>,
{
<<Self as GraphNodeAccess<I>>::Node as Node<
IN,
OUT,
<Self as GraphNodeTypes<I, IN, OUT>>::InP,
<Self as GraphNodeTypes<I, IN, OUT>>::OutP,
>>::policy(<Self as GraphNodeAccess<I>>::node_ref(self))
}
}
pub type EdgeOccupancyBuf<const E: usize> = [EdgeOccupancy; E];
#[cfg(feature = "std")]
pub trait ScopedGraphApi<const NODE_COUNT: usize, const EDGE_COUNT: usize>:
GraphApi<NODE_COUNT, EDGE_COUNT>
{
fn run_scoped<C, T, S>(&mut self, clock: C, telemetry: T, scheduler: S)
where
C: PlatformClock + Clone + Send + Sync + 'static,
T: Telemetry + Clone + Send + 'static,
S: crate::scheduling::WorkerScheduler + 'static;
}