1use std::sync::Arc;
32
33use graphrefly_core::{Core, FnId, HandleId, NodeId, OperatorOp, OperatorOpts};
34
35use crate::binding::OperatorBinding;
36
37#[derive(Copy, Clone, Debug)]
41#[must_use = "the operator's NodeId is the value of registering it"]
42pub struct OperatorRegistration {
43 pub node: NodeId,
44 pub fn_id: FnId,
45}
46
47impl OperatorRegistration {
48 #[must_use]
50 pub fn into_node(self) -> NodeId {
51 self.node
52 }
53}
54
55impl From<OperatorRegistration> for NodeId {
56 fn from(r: OperatorRegistration) -> Self {
57 r.node
58 }
59}
60
61pub fn map<F>(
77 core: &Core,
78 binding: &Arc<dyn OperatorBinding>,
79 source: NodeId,
80 project: F,
81) -> OperatorRegistration
82where
83 F: Fn(HandleId) -> HandleId + Send + Sync + 'static,
84{
85 map_with(core, binding, source, project, OperatorOpts::default())
86}
87
88pub fn map_with<F>(
90 core: &Core,
91 binding: &Arc<dyn OperatorBinding>,
92 source: NodeId,
93 project: F,
94 opts: OperatorOpts,
95) -> OperatorRegistration
96where
97 F: Fn(HandleId) -> HandleId + Send + Sync + 'static,
98{
99 let fn_id = binding.register_projector(Box::new(project));
100 let node = core
101 .register_operator(&[source], OperatorOp::Map { fn_id }, opts)
102 .expect(
103 "invariant: caller has validated dep ids and seed before calling register_operator",
104 );
105 OperatorRegistration { node, fn_id }
106}
107
108pub fn filter<F>(
115 core: &Core,
116 binding: &Arc<dyn OperatorBinding>,
117 source: NodeId,
118 predicate: F,
119) -> OperatorRegistration
120where
121 F: Fn(HandleId) -> bool + Send + Sync + 'static,
122{
123 filter_with(core, binding, source, predicate, OperatorOpts::default())
124}
125
126pub fn filter_with<F>(
128 core: &Core,
129 binding: &Arc<dyn OperatorBinding>,
130 source: NodeId,
131 predicate: F,
132 opts: OperatorOpts,
133) -> OperatorRegistration
134where
135 F: Fn(HandleId) -> bool + Send + Sync + 'static,
136{
137 let fn_id = binding.register_predicate(Box::new(predicate));
138 let node = core
139 .register_operator(&[source], OperatorOp::Filter { fn_id }, opts)
140 .expect(
141 "invariant: caller has validated dep ids and seed before calling register_operator",
142 );
143 OperatorRegistration { node, fn_id }
144}
145
146pub fn scan<F>(
158 core: &Core,
159 binding: &Arc<dyn OperatorBinding>,
160 source: NodeId,
161 fold: F,
162 seed: HandleId,
163) -> OperatorRegistration
164where
165 F: Fn(HandleId, HandleId) -> HandleId + Send + Sync + 'static,
166{
167 scan_with(core, binding, source, fold, seed, OperatorOpts::default())
168}
169
170pub fn scan_with<F>(
172 core: &Core,
173 binding: &Arc<dyn OperatorBinding>,
174 source: NodeId,
175 fold: F,
176 seed: HandleId,
177 opts: OperatorOpts,
178) -> OperatorRegistration
179where
180 F: Fn(HandleId, HandleId) -> HandleId + Send + Sync + 'static,
181{
182 let fn_id = binding.register_folder(Box::new(fold));
183 let node = core
184 .register_operator(&[source], OperatorOp::Scan { fn_id, seed }, opts)
185 .expect(
186 "invariant: caller has validated dep ids and seed before calling register_operator",
187 );
188 OperatorRegistration { node, fn_id }
189}
190
191pub fn reduce<F>(
199 core: &Core,
200 binding: &Arc<dyn OperatorBinding>,
201 source: NodeId,
202 fold: F,
203 seed: HandleId,
204) -> OperatorRegistration
205where
206 F: Fn(HandleId, HandleId) -> HandleId + Send + Sync + 'static,
207{
208 reduce_with(core, binding, source, fold, seed, OperatorOpts::default())
209}
210
211pub fn reduce_with<F>(
213 core: &Core,
214 binding: &Arc<dyn OperatorBinding>,
215 source: NodeId,
216 fold: F,
217 seed: HandleId,
218 opts: OperatorOpts,
219) -> OperatorRegistration
220where
221 F: Fn(HandleId, HandleId) -> HandleId + Send + Sync + 'static,
222{
223 let fn_id = binding.register_folder(Box::new(fold));
224 let node = core
225 .register_operator(&[source], OperatorOp::Reduce { fn_id, seed }, opts)
226 .expect(
227 "invariant: caller has validated dep ids and seed before calling register_operator",
228 );
229 OperatorRegistration { node, fn_id }
230}
231
232pub fn distinct_until_changed<F>(
249 core: &Core,
250 binding: &Arc<dyn OperatorBinding>,
251 source: NodeId,
252 equals: F,
253) -> OperatorRegistration
254where
255 F: Fn(HandleId, HandleId) -> bool + Send + Sync + 'static,
256{
257 distinct_until_changed_with(core, binding, source, equals, OperatorOpts::default())
258}
259
260pub fn distinct_until_changed_with<F>(
262 core: &Core,
263 binding: &Arc<dyn OperatorBinding>,
264 source: NodeId,
265 equals: F,
266 opts: OperatorOpts,
267) -> OperatorRegistration
268where
269 F: Fn(HandleId, HandleId) -> bool + Send + Sync + 'static,
270{
271 let equals_fn_id = binding.register_equals(Box::new(equals));
272 let node = core
273 .register_operator(
274 &[source],
275 OperatorOp::DistinctUntilChanged { equals_fn_id },
276 opts,
277 )
278 .expect(
279 "invariant: caller has validated dep ids and seed before calling register_operator",
280 );
281 OperatorRegistration {
282 node,
283 fn_id: equals_fn_id,
284 }
285}
286
287pub fn pairwise<F>(
296 core: &Core,
297 binding: &Arc<dyn OperatorBinding>,
298 source: NodeId,
299 pack: F,
300) -> OperatorRegistration
301where
302 F: Fn(HandleId, HandleId) -> HandleId + Send + Sync + 'static,
303{
304 pairwise_with(core, binding, source, pack, OperatorOpts::default())
305}
306
307pub fn pairwise_with<F>(
309 core: &Core,
310 binding: &Arc<dyn OperatorBinding>,
311 source: NodeId,
312 pack: F,
313 opts: OperatorOpts,
314) -> OperatorRegistration
315where
316 F: Fn(HandleId, HandleId) -> HandleId + Send + Sync + 'static,
317{
318 let fn_id = binding.register_pairwise_packer(Box::new(pack));
319 let node = core
320 .register_operator(&[source], OperatorOp::Pairwise { fn_id }, opts)
321 .expect(
322 "invariant: caller has validated dep ids and seed before calling register_operator",
323 );
324 OperatorRegistration { node, fn_id }
325}