exegraph/
lib.rs

1#![no_std]
2use core::array;
3
4pub struct Node<
5    P: Processor<D, MAX_IN, MAX_OUT>,
6    D: Default,
7    const MAX_IN: usize,
8    const MAX_OUT: usize,
9> {
10    processor: Option<P>,
11    read: [D; MAX_OUT],
12    write: [D; MAX_OUT],
13}
14
15impl<P: Processor<D, MAX_IN, MAX_OUT>, D: Default, const MAX_IN: usize, const MAX_OUT: usize>
16    Node<P, D, MAX_IN, MAX_OUT>
17{
18    pub fn new(processor: Option<P>) -> Self {
19        Self {
20            processor,
21            read: array::from_fn(|_| D::default()),
22            write: array::from_fn(|_| D::default()),
23        }
24    }
25}
26
27pub trait Processor<D, const MAX_IN: usize, const MAX_OUT: usize> {
28    fn process(&mut self, inputs: &[Option<&D>; MAX_IN]) -> [D; MAX_OUT];
29}
30
31pub struct StaticGraph<
32    P: Processor<D, MAX_IN, MAX_OUT>,
33    D: Default,
34    const MAX_IN: usize,
35    const MAX_OUT: usize,
36    const MAX_NODES: usize,
37> {
38    nodes: [Node<P, D, MAX_IN, MAX_OUT>; MAX_NODES],
39    used: [bool; MAX_NODES],
40    connections: [[Option<(usize, usize)>; MAX_IN]; MAX_NODES],
41}
42
43pub struct NodeHandle(usize);
44
45impl<
46        P: Processor<D, MAX_IN, MAX_OUT>,
47        D: Default,
48        const MAX_IN: usize,
49        const MAX_OUT: usize,
50        const MAX_NODES: usize,
51    > StaticGraph<P, D, MAX_IN, MAX_OUT, MAX_NODES>
52{
53    pub fn new() -> Self {
54        Self {
55            nodes: array::from_fn(|_| Node::new(None)),
56            used: [false; MAX_NODES],
57            connections: [[None; MAX_IN]; MAX_NODES],
58        }
59    }
60    pub fn process(&mut self) {
61        for i in 0..MAX_NODES {
62            core::mem::swap(&mut self.nodes[i].read, &mut self.nodes[i].write)
63        }
64        for i in 0..MAX_NODES {
65            if self.used[i] {
66                let mut inputs = array::from_fn(|_| None);
67                for (j, input) in self.connections[i].iter().enumerate() {
68                    if let Some((in_node, in_port)) = input {
69                        inputs[j] = Some(&self.nodes[*in_node].read[*in_port]);
70                    }
71                }
72                if let Some(ref mut processor) = self.nodes[i].processor {
73                    self.nodes[i].write = processor.process(&inputs);
74                }
75            }
76        }
77    }
78
79    pub fn add_node(&mut self, processor: P) -> Option<NodeHandle> {
80        for i in 0..MAX_NODES {
81            if !self.used[i] {
82                self.nodes[i].processor = Some(processor);
83                self.used[i] = true;
84                return Some(NodeHandle(i));
85            }
86        }
87        return None;
88    }
89
90    pub fn remove_node(&mut self, idx: NodeHandle) {
91        let idx = idx.0;
92        self.used[idx] = false;
93
94        for i in self.connections.iter_mut() {
95            for j in i.iter_mut() {
96                if let Some((in_node, _)) = *j {
97                    if in_node == idx {
98                        *j = None;
99                    }
100                }
101            }
102        }
103    }
104    pub fn set_edge(
105        &mut self,
106        to: &NodeHandle,
107        to_sink: usize,
108        from: &NodeHandle,
109        from_source: usize,
110    ) {
111        self.connections[to.0][to_sink] = Some((from.0, from_source));
112    }
113    pub fn unset_edge(&mut self, to: &NodeHandle, to_sink: usize) {
114        self.connections[to.0][to_sink] = None;
115    }
116}