linkspace/
interop.rs

1// Copyright Anton Sol
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use crate::query::LkQuery;
8use linkspace_core::query::Query as QueryImpl;
9#[doc(hidden)]
10impl From<LkQuery> for QueryImpl {
11    fn from(val: LkQuery) -> Self {
12        val.0
13    }
14}
15#[doc(hidden)]
16impl From<QueryImpl> for LkQuery {
17    fn from(value: QueryImpl) -> Self {
18        LkQuery(value)
19    }
20}
21impl crate::query::LkQuery {
22    #[doc(hidden)]
23    pub fn as_impl(&self) -> &QueryImpl {
24        unsafe { &*(self as *const LkQuery as *const QueryImpl) }
25    }
26    #[doc(hidden)]
27    pub fn from_impl(q: &QueryImpl) -> &LkQuery {
28        unsafe { &*(q as *const QueryImpl as *const LkQuery) }
29    }
30}
31
32#[cfg(any(feature = "lmdb", feature = "inmem"))]
33pub mod sys_interop {
34    use crate::system::LkSystem;
35    use std::ops::ControlFlow;
36
37    use linkspace_core::{prelude::Point, query::WatchIDRef};
38    pub use linkspace_system::System;
39    use linkspace_system::{
40        handlers::{PointStreamHandler, StopReason},
41        thread_local::{use_sys, with_system},
42    };
43    #[doc(hidden)]
44    impl From<System> for LkSystem {
45        fn from(value: System) -> Self {
46            LkSystem(value)
47        }
48    }
49    #[doc(hidden)]
50    impl From<LkSystem> for System {
51        fn from(val: LkSystem) -> Self {
52            val.0
53        }
54    }
55    impl LkSystem {
56        #[doc(hidden)]
57        pub fn as_impl(&self) -> &System {
58            unsafe { &*(self as *const LkSystem as *const System) }
59        }
60        #[doc(hidden)]
61        pub fn from_impl(lks: &System) -> &LkSystem {
62            unsafe { &*(lks as *const System as *const LkSystem) }
63        }
64        #[doc(hidden)]
65        pub fn active() -> LkSystem {
66            LkSystem(linkspace_system::thread_local::get_system().unwrap())
67        }
68    }
69    impl linkspace_system::eval::OpenSystem for &LkSystem {
70        fn lk(self) -> anyhow::Result<System> {
71            Ok(self.0.clone())
72        }
73    }
74
75    // Wrapper to hide PointStreamHandler and its type arguments
76    #[derive(Debug, Clone)]
77    pub struct Handler<T: ?Sized>(pub T);
78    use crate::query::LkQuery;
79
80    use crate::system::cb::PointHandler;
81    impl<T: PointHandler + ?Sized + 'static> linkspace_system::handlers::PointStreamHandler
82        for Handler<T>
83    {
84        fn handle_point(
85            &mut self,
86            point: &dyn Point,
87            watch_id: Option<&WatchIDRef>,
88            rx: &System,
89        ) -> ControlFlow<()> {
90            use_sys(rx, || self.0.on_point(point, watch_id))
91        }
92        fn stopped(
93            &mut self,
94            query: &linkspace_core::prelude::Query,
95            sys: &System,
96            reason: StopReason,
97            total: u64,
98            watched: u64,
99        ) {
100            let query = LkQuery::from_impl(query);
101            use_sys(sys, || self.0.on_close(query, reason, total, watched))
102        }
103    }
104    impl<T: PointHandler + 'static> linkspace_system::handlers::HeapPointStreamHandler for Handler<T> {}
105
106    impl<T: PointStreamHandler + ?Sized + 'static> PointHandler for Handler<T> {
107        fn on_point(&mut self, point: &dyn Point, watch: Option<&WatchIDRef>) -> ControlFlow<()> {
108            with_system(|lks| self.0.handle_point(point, watch, &lks))
109        }
110
111        fn on_close(
112            &mut self,
113            q: &LkQuery,
114            reason: StopReason,
115            total_calls: u64,
116            watch_calls: u64,
117        ) {
118            with_system(|lks| {
119                self.0
120                    .stopped(q.as_impl(), &lks, reason, total_calls, watch_calls)
121            })
122        }
123    }
124}