rsdiff_graphs/scg/
node.rs

1/*
2    Appellation: node <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5//! # Node
6//!
7//! A computational graph relies on weighted nodes to represent constants, operations, and variables.
8//! The edges connecting to any given node are considered to be inputs and help to determine the flow of information
9use crate::NodeIndex;
10use rsdiff::id::AtomicId;
11use rsdiff::ops::{Op, Operator};
12use smart_default::SmartDefault;
13use strum::{Display, EnumCount, EnumIs, VariantNames};
14
15pub trait ScgNode {
16    fn id(&self) -> AtomicId;
17    fn name(&self) -> &str;
18}
19
20macro_rules! impl_scg_node {
21    ($($ty:ty),*) => {
22        $(
23            impl ScgNode for $ty {
24                fn id(&self) -> AtomicId {
25                    self.id
26                }
27
28                fn name(&self) -> &str {
29                    &self.name
30                }
31            }
32        )*
33    };
34
35}
36
37impl_scg_node!(Placeholder, Operation);
38
39#[derive(
40    Clone,
41    Debug,
42    Display,
43    EnumCount,
44    EnumIs,
45    Eq,
46    Hash,
47    Ord,
48    PartialEq,
49    PartialOrd,
50    SmartDefault,
51    VariantNames,
52)]
53#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize,))]
54pub enum Node {
55    Operation(Operation),
56    #[default]
57    Placeholder(Placeholder),
58}
59
60impl Node {
61    pub fn operation(inputs: impl IntoIterator<Item = NodeIndex>, op: impl Into<Op>) -> Self {
62        Node::Operation(Operation::new(inputs, op))
63    }
64
65    pub fn placeholder(name: impl ToString) -> Self {
66        Node::Placeholder(Placeholder::new(name))
67    }
68
69    pub fn id(&self) -> AtomicId {
70        match self {
71            Node::Operation(op) => op.id(),
72            Node::Placeholder(ph) => ph.id(),
73        }
74    }
75
76    pub fn inputs(&self) -> Option<&[NodeIndex]> {
77        match self {
78            Node::Operation(op) => Some(op.inputs()),
79            _ => None,
80        }
81    }
82
83    pub fn name(&self) -> &str {
84        match self {
85            Node::Operation(op) => op.name(),
86            Node::Placeholder(ph) => ph.name(),
87        }
88    }
89
90    pub fn op(&self) -> Option<&Op> {
91        match self {
92            Node::Operation(op) => Some(op.operation()),
93            _ => None,
94        }
95    }
96}
97
98#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
99#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize,))]
100pub struct Placeholder {
101    id: AtomicId,
102    name: String,
103}
104
105impl Placeholder {
106    pub fn new(name: impl ToString) -> Self {
107        Self {
108            id: AtomicId::new(),
109            name: name.to_string(),
110        }
111    }
112
113    pub fn with_name(mut self, name: impl ToString) -> Self {
114        self.name = name.to_string();
115        self
116    }
117
118    pub const fn id(&self) -> AtomicId {
119        self.id
120    }
121
122    pub fn name(&self) -> &str {
123        &self.name
124    }
125}
126
127#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
128#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize,))]
129pub struct Operation {
130    id: AtomicId,
131    inputs: Vec<NodeIndex>,
132    name: String,
133    op: Op,
134}
135
136impl Operation {
137    pub fn new(inputs: impl IntoIterator<Item = NodeIndex>, op: impl Into<Op>) -> Self {
138        let op = op.into();
139        Self {
140            id: AtomicId::new(),
141            inputs: Vec::from_iter(inputs),
142            name: op.name().to_string(),
143            op,
144        }
145    }
146
147    pub fn with_inputs(mut self, inputs: impl IntoIterator<Item = NodeIndex>) -> Self {
148        self.inputs = Vec::from_iter(inputs);
149        self
150    }
151
152    pub fn with_name(mut self, name: impl ToString) -> Self {
153        self.name = name.to_string();
154        self
155    }
156
157    pub fn clear(&mut self) {
158        self.inputs.clear();
159    }
160
161    pub fn inputs(&self) -> &[NodeIndex] {
162        &self.inputs
163    }
164
165    pub fn inputs_mut(&mut self) -> &mut Vec<NodeIndex> {
166        &mut self.inputs
167    }
168
169    pub fn name(&self) -> &str {
170        &self.name
171    }
172
173    pub fn operation(&self) -> &Op {
174        &self.op
175    }
176}