standing_relations/core/op/
split.rs

1use 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}