standing_relations/core/op/
split.rs1use std::{cell::RefCell, rc::Rc};
2
3use crate::core::{
4 dirty::DirtyReceive,
5 pipes::{self, Receiver, Sender},
6 relation::RelationInner,
7 Op_, Relation,
8};
9
10pub struct Split<T, C: Op_<T = (L, R)>, L, R> {
11 inner: Rc<RefCell<SplitInner<C, L, R>>>,
12 receiver: Receiver<T>,
13}
14
15struct SplitInner<C: Op_<T = (L, R)>, L, R> {
16 inner: RelationInner<C>,
17 left_sender: Sender<L>,
18 right_sender: Sender<R>,
19 dirty: DirtyReceive,
20}
21
22impl<T, C: Op_<T = (L, R)>, L, R> Op_ for Split<T, C, L, R> {
23 type T = T;
24
25 fn foreach<'a>(&'a mut self, mut continuation: impl FnMut(Self::T) + 'a) {
26 if self.inner.borrow_mut().dirty.take_status() {
27 let mut inner = self.inner.borrow_mut();
28 let data = inner.inner.get_vec();
29 for (xl, xr) in data {
30 inner.left_sender.send(xl);
31 inner.right_sender.send(xr)
32 }
33 }
34 for x in self.receiver.receive() {
35 continuation(x)
36 }
37 }
38
39 fn get_type_name() -> &'static str {
40 "split"
41 }
42}
43
44#[allow(clippy::type_complexity)]
45impl<C: Op_<T = (L, R)>, L, R> Relation<C> {
46 pub fn split_(self) -> (Relation<Split<L, C, L, R>>, Relation<Split<R, C, L, R>>) {
47 let mut this_dirty = self.dirty.into_receive();
48 let left_dirty = this_dirty.add_target();
49 let right_dirty = this_dirty.add_target();
50 let (left_sender, left_receiver) = pipes::new();
51 let (right_sender, right_receiver) = pipes::new();
52 let inner = Rc::new(RefCell::new(SplitInner {
53 inner: self.inner,
54 left_sender,
55 right_sender,
56 dirty: this_dirty,
57 }));
58 let left_result = self.context_tracker.clone().add_relation(
59 left_dirty,
60 Split {
61 inner: Rc::clone(&inner),
62 receiver: left_receiver,
63 },
64 vec![self.tracking_index],
65 );
66 let right_result = self.context_tracker.add_relation(
67 right_dirty,
68 Split {
69 inner,
70 receiver: right_receiver,
71 },
72 vec![self.tracking_index],
73 );
74 (left_result, right_result)
75 }
76}