pytauri_core/ext_mod_impl/lib/
emitter.rs

1use pyo3::prelude::*;
2use tauri::Emitter as _;
3
4use crate::{
5    ext_mod::{manager_method_impl, EventTarget, ImplManager},
6    utils::{PyResultExt as _, TauriError},
7};
8
9/// The Implementers of [tauri::Emitter].
10pub type ImplEmitter = ImplManager;
11
12/// See also: [tauri::Emitter].
13//
14// `subclass` for implementing `emit`, `emit_to`, etc. methods from the Python side.
15#[pyclass(frozen, subclass)]
16#[non_exhaustive]
17pub struct Emitter;
18
19#[pymethods]
20impl Emitter {
21    #[staticmethod]
22    fn emit_str(py: Python<'_>, slf: ImplEmitter, event: &str, payload: String) -> PyResult<()> {
23        manager_method_impl!(py, &slf, [ungil], |manager| {
24            manager.emit_str(event, payload).map_err(TauriError::from)
25        })??;
26        Ok(())
27    }
28
29    #[staticmethod]
30    fn emit_str_to(
31        py: Python<'_>,
32        slf: ImplEmitter,
33        target: Py<EventTarget>,
34        event: &str,
35        payload: String,
36    ) -> PyResult<()> {
37        let target = target.get().to_tauri(py)?;
38
39        manager_method_impl!(py, &slf, [ungil], |manager| {
40            manager
41                .emit_str_to(target, event, payload)
42                .map_err(TauriError::from)
43        })??;
44        Ok(())
45    }
46
47    #[staticmethod]
48    fn emit_str_filter(
49        py: Python<'_>,
50        slf: ImplEmitter,
51        event: &str,
52        payload: String,
53        filter: Bound<PyAny>,
54    ) -> PyResult<()> {
55        // We can't release the GIL here, because `rs_filter` will be used as `iter.filter(|..| rs_filter(..))`;
56        // if we frequently release and acquire the GIL, maybe it will cause performance problems.
57        // TODO, PERF: only tauri itself can release GIL in `emit_str_filter`.
58        let rs_filter = |target: &tauri::EventTarget| -> bool {
59            let target = EventTarget::from_tauri(py, target);
60            let filter_result = filter.call1((target,));
61            let filter_ret = filter_result.unwrap_unraisable_py_result(py, Some(&filter), || {
62                "Python exception occurred in emitter filter"
63            });
64            let extract_result = filter_ret.extract::<bool>();
65            extract_result.unwrap_unraisable_py_result(py, Some(&filter_ret), || {
66                "emitter filter return non-bool value"
67            })
68        };
69
70        manager_method_impl!(py, &slf, |_py, manager| {
71            manager
72                .emit_str_filter(event, payload, rs_filter)
73                .map_err(TauriError::from)
74        })??;
75        Ok(())
76    }
77}