use alloc::vec::Vec;
use core::any::Any;
use super::super::data::Stream;
use super::super::error::ExecError;
use super::super::params::LocalParams;
use super::super::registry::{GraphId, NodeId, RuntimeParams, gid};
use super::Exec;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) struct Edge(pub(crate) u32);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Dest {
Unassigned,
Processed,
Trigger,
Follow,
}
#[derive(Copy, Clone, Debug)]
struct EdgeState {
rtsid: u32,
dest: Dest,
succession_pos: usize,
}
#[derive(Debug)]
struct DestDesc {
gid: GraphId,
params: Option<RuntimeParams>,
n_inputs: usize,
first_rtsid: usize,
}
#[derive(Copy, Clone, Debug)]
pub(crate) struct Effective<'g> {
pub(crate) params: &'g LocalParams,
pub(crate) custom_graphs: &'g [GraphId],
pub(crate) custom_nodes: &'g [NodeId],
pub(crate) mparam: Option<&'g (dyn Any + Send + Sync)>,
}
#[derive(Debug)]
pub(crate) struct Successor {
pub(crate) gid: GraphId,
pub(crate) params: Option<RuntimeParams>,
pub(crate) inputs: Vec<u32>,
}
pub(crate) struct GraphCx<'g, 'e, 'a> {
pub(crate) ex: &'g mut Exec<'e, 'a>,
pub(crate) eff: Effective<'g>,
pub(crate) depth: u32,
edges: Vec<EdgeState>,
dests: Vec<DestDesc>,
rtsids: Vec<u32>,
status: Result<(), ExecError>,
}
impl<'g, 'e, 'a> GraphCx<'g, 'e, 'a> {
pub(crate) fn new(
ex: &'g mut Exec<'e, 'a>,
eff: Effective<'g>,
depth: u32,
inputs: &[u32],
) -> Self {
let edges = inputs
.iter()
.map(|&rtsid| EdgeState {
rtsid,
dest: Dest::Unassigned,
succession_pos: 0,
})
.collect();
Self {
ex,
eff,
depth,
edges,
dests: Vec::new(),
rtsids: Vec::new(),
status: Ok(()),
}
}
pub(crate) fn input_edges(&self) -> Vec<Edge> {
(0..self.edges.len()).map(|n| Edge(n as u32)).collect()
}
pub(crate) fn data(&self, edge: Edge) -> Result<&Stream<'a>, ExecError> {
let state = self
.edges
.get(edge.0 as usize)
.ok_or(ExecError::GraphInvalid)?;
self.ex
.rt
.stream(state.rtsid)
.ok_or(ExecError::GraphInvalid)
}
pub(crate) fn edge_rtsid(&self, edge: Edge) -> Result<u32, ExecError> {
self.edges
.get(edge.0 as usize)
.map(|state| state.rtsid)
.ok_or(ExecError::GraphInvalid)
}
pub(crate) fn set_metadata(
&mut self,
edge: Edge,
id: i32,
value: i32,
) -> Result<(), ExecError> {
let rtsid = self
.edges
.get(edge.0 as usize)
.ok_or(ExecError::GraphInvalid)?
.rtsid;
self.ex
.rt
.streams
.get_mut(rtsid as usize)
.and_then(|slot| slot.stream.as_mut())
.ok_or(ExecError::GraphInvalid)?
.set_metadata(id, value);
Ok(())
}
pub(crate) fn run_node(
&mut self,
node: NodeId,
inputs: &[Edge],
local: Option<&LocalParams>,
) -> Result<Vec<Edge>, ExecError> {
let mut rtsids = Vec::with_capacity(inputs.len());
for edge in inputs {
let state = self
.edges
.get(edge.0 as usize)
.ok_or(ExecError::GraphInvalid)?;
if state.dest != Dest::Unassigned {
return Err(ExecError::SuccessorAlreadySet);
}
rtsids.push(state.rtsid);
}
let run = self.ex.run_node(node, &rtsids, local)?;
for edge in inputs {
self.edges[edge.0 as usize].dest = Dest::Processed;
}
let first = self.edges.len() as u32;
for n in 0..run.n_out {
self.edges.push(EdgeState {
rtsid: run.start_out + n,
dest: Dest::Unassigned,
succession_pos: 0,
});
}
Ok((0..run.n_out).map(|n| Edge(first + n)).collect())
}
pub(crate) fn set_destination(
&mut self,
edges: &[Edge],
graph: GraphId,
params: Option<RuntimeParams>,
) -> Result<(), ExecError> {
if edges.is_empty() {
return Err(ExecError::SuccessorInputs);
}
let def = self.ex.reg.graph(graph)?;
let n_ports = def.inputs.len();
let count_ok = if def.last_variable {
edges.len() + 1 >= n_ports
} else {
edges.len() == n_ports
};
if !count_ok {
return Err(ExecError::SuccessorInputs);
}
for (n, edge) in edges.iter().enumerate() {
let state = self
.edges
.get_mut(edge.0 as usize)
.ok_or(ExecError::GraphInvalid)?;
if state.dest != Dest::Unassigned {
self.status = Err(ExecError::SuccessorAlreadySet);
return Err(ExecError::SuccessorAlreadySet);
}
state.dest = if n == 0 { Dest::Trigger } else { Dest::Follow };
state.succession_pos = self.dests.len();
self.rtsids.push(state.rtsid);
}
self.dests.push(DestDesc {
gid: graph,
params: params.filter(|params| !params.is_empty()),
n_inputs: edges.len(),
first_rtsid: self.rtsids.len() - edges.len(),
});
Ok(())
}
pub(crate) fn finish(self, result: Result<(), ExecError>) -> Result<Vec<Successor>, ExecError> {
result?;
self.status?;
let permissive = self.ex.p.permissive;
let mut successors = Vec::new();
for state in &self.edges {
match state.dest {
Dest::Trigger => {
let desc = &self.dests[state.succession_pos];
successors.push(Successor {
gid: desc.gid,
params: desc.params.clone(),
inputs: self.rtsids[desc.first_rtsid..desc.first_rtsid + desc.n_inputs]
.to_vec(),
});
}
Dest::Unassigned if permissive => successors.push(Successor {
gid: gid::COMPRESS_GENERIC,
params: None,
inputs: alloc::vec![state.rtsid],
}),
Dest::Unassigned => return Err(ExecError::SuccessorMissing),
Dest::Processed | Dest::Follow => {}
}
}
Ok(successors)
}
pub(crate) fn is_node_supported(&self, node: NodeId) -> bool {
self.ex.node_supported(node)
}
pub(crate) fn mparam(&self) -> Option<&'g (dyn Any + Send + Sync)> {
self.eff.mparam
}
pub(crate) fn int_metadata(&self, edge: Edge, id: i32) -> Result<Option<i32>, ExecError> {
Ok(self
.data(edge)?
.metadata()
.iter()
.find(|(key, _)| *key == id)
.map(|&(_, value)| value))
}
}
pub(crate) const MPARAM_REF_ID: i32 = i32::MIN + 1;