tauri_plugin_pytauri/
lib.rs1mod commands;
5mod gil_runtime;
6
7use std::error::Error;
8use std::fmt::Display;
9use std::ops::Deref;
10
11use pyo3::exceptions::PyRuntimeError;
12use pyo3::prelude::*;
13use pytauri_core::tauri_runtime::Runtime as PyTauriRuntime;
14use tauri::plugin::{Builder, TauriPlugin};
15use tauri::{Manager, Runtime};
16
17use crate::commands::invoke_handler;
18
19const PLUGIN_NAME: &str = "pytauri";
20
21type PyInvokeHandlerType = PyObject;
22
23struct PyInvokeHandler(PyInvokeHandlerType);
24
25impl Deref for PyInvokeHandler {
26 type Target = PyInvokeHandlerType;
27
28 fn deref(&self) -> &Self::Target {
29 &self.0
30 }
31}
32
33impl PyInvokeHandler {
34 fn new(handler: PyInvokeHandlerType) -> Self {
35 Self(handler)
36 }
37}
38
39pub fn init(py_invoke_handler: PyInvokeHandlerType) -> TauriPlugin<PyTauriRuntime> {
55 Builder::<PyTauriRuntime>::new(PLUGIN_NAME)
56 .invoke_handler(invoke_handler)
57 .setup(|app_handle, _plugin_api| {
58 if !app_handle.manage(PyInvokeHandler::new(py_invoke_handler)) {
60 unreachable!(
61 "`PyInvokeHandler` is private, so it is impossible for other crates to manage it"
62 )
63 }
64 Ok(())
65 })
66 .build()
67}
68
69mod sealed {
70 use super::*;
71
72 pub trait SealedTrait<R> {}
73
74 impl<R: Runtime, T: Manager<R>> SealedTrait<R> for T {}
75}
76
77#[derive(Debug)]
79pub struct PyInvokeHandlerStateError;
80
81impl Display for PyInvokeHandlerStateError {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 write!(
84 f,
85 "Failed to get `PyInvokeHandler` from state, maybe `{}` is not initialized",
86 env!("CARGO_PKG_NAME")
87 )
88 }
89}
90
91impl Error for PyInvokeHandlerStateError {}
92
93impl From<PyInvokeHandlerStateError> for PyErr {
94 fn from(value: PyInvokeHandlerStateError) -> Self {
95 PyRuntimeError::new_err(value.to_string())
96 }
97}
98
99pub type PyInvokeHandlerStateResult<T> = Result<T, PyInvokeHandlerStateError>;
100
101pub trait PyInvokeHandlerExt<R: Runtime>: Manager<R> + sealed::SealedTrait<R> {
103 fn try_py_invoke_handler(
104 &self,
105 ) -> PyInvokeHandlerStateResult<impl Deref<Target = PyInvokeHandlerType>> {
106 self.try_state::<PyInvokeHandler>()
107 .map(|state| state.inner().deref())
108 .ok_or(PyInvokeHandlerStateError)
109 }
110
111 fn py_invoke_handler(&self) -> impl Deref<Target = PyInvokeHandlerType> {
115 self.try_py_invoke_handler().unwrap()
116 }
117}
118
119impl<R: Runtime, T: Manager<R>> PyInvokeHandlerExt<R> for T {}