1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#![no_std]
use core::array;

pub struct Node<
    P: Processor<D, MAX_IN, MAX_OUT>,
    D: Default,
    const MAX_IN: usize,
    const MAX_OUT: usize,
> {
    processor: Option<P>,
    read: [D; MAX_OUT],
    write: [D; MAX_OUT],
}

impl<P: Processor<D, MAX_IN, MAX_OUT>, D: Default, const MAX_IN: usize, const MAX_OUT: usize>
    Node<P, D, MAX_IN, MAX_OUT>
{
    pub fn new(processor: Option<P>) -> Self {
        Self {
            processor,
            read: array::from_fn(|_| D::default()),
            write: array::from_fn(|_| D::default()),
        }
    }
}

pub trait Processor<D, const MAX_IN: usize, const MAX_OUT: usize> {
    fn process(&mut self, inputs: &[Option<&D>; MAX_IN]) -> [D; MAX_OUT];
}

pub struct StaticGraph<
    P: Processor<D, MAX_IN, MAX_OUT>,
    D: Default,
    const MAX_IN: usize,
    const MAX_OUT: usize,
    const MAX_NODES: usize,
> {
    nodes: [Node<P, D, MAX_IN, MAX_OUT>; MAX_NODES],
    used: [bool; MAX_NODES],
    connections: [[Option<(usize, usize)>; MAX_IN]; MAX_NODES],
}

pub struct NodeHandle(usize);

impl<
        P: Processor<D, MAX_IN, MAX_OUT>,
        D: Default,
        const MAX_IN: usize,
        const MAX_OUT: usize,
        const MAX_NODES: usize,
    > StaticGraph<P, D, MAX_IN, MAX_OUT, MAX_NODES>
{
    pub fn new() -> Self {
        Self {
            nodes: array::from_fn(|_| Node::new(None)),
            used: [false; MAX_NODES],
            connections: [[None; MAX_IN]; MAX_NODES],
        }
    }
    pub fn process(&mut self) {
        for i in 0..MAX_NODES {
            core::mem::swap(&mut self.nodes[i].read, &mut self.nodes[i].write)
        }
        for i in 0..MAX_NODES {
            if self.used[i] {
                let mut inputs = array::from_fn(|_| None);
                for (j, input) in self.connections[i].iter().enumerate() {
                    if let Some((in_node, in_port)) = input {
                        inputs[j] = Some(&self.nodes[*in_node].read[*in_port]);
                    }
                }
                if let Some(ref mut processor) = self.nodes[i].processor {
                    self.nodes[i].write = processor.process(&inputs);
                }
            }
        }
    }

    pub fn add_node(&mut self, processor: P) -> Option<NodeHandle> {
        for i in 0..MAX_NODES {
            if !self.used[i] {
                self.nodes[i].processor = Some(processor);
                self.used[i] = true;
                return Some(NodeHandle(i));
            }
        }
        return None;
    }

    pub fn remove_node(&mut self, idx: NodeHandle) {
        let idx = idx.0;
        self.used[idx] = false;

        for i in self.connections.iter_mut() {
            for j in i.iter_mut() {
                if let Some((in_node, _)) = *j {
                    if in_node == idx {
                        *j = None;
                    }
                }
            }
        }
    }
    pub fn set_edge(
        &mut self,
        to: &NodeHandle,
        to_sink: usize,
        from: &NodeHandle,
        from_source: usize,
    ) {
        self.connections[to.0][to_sink] = Some((from.0, from_source));
    }
    pub fn unset_edge(&mut self, to: &NodeHandle, to_sink: usize) {
        self.connections[to.0][to_sink] = None;
    }
}