rsdiff_graphs/scg/
node.rs1use 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}