use std::{
any::Any,
error::Error,
fmt::{Display, Formatter},
panic::panic_any,
};
use pyo3::{exceptions::PyRuntimeError, prelude::*};
#[derive(Debug)]
pub struct TauriError(tauri::Error);
impl Display for TauriError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.0, f)
}
}
impl Error for TauriError {}
impl From<TauriError> for PyErr {
fn from(value: TauriError) -> Self {
PyRuntimeError::new_err(value.0.to_string())
}
}
impl From<tauri::Error> for TauriError {
fn from(value: tauri::Error) -> Self {
Self(value)
}
}
pub type TauriResult<T> = Result<T, TauriError>;
pub(crate) trait PyResultExt {
type Output;
fn unwrap_unraisable_py_result<M>(
self,
py: Python<'_>,
obj: Option<&Bound<'_, PyAny>>,
msg: impl FnOnce() -> M,
) -> Self::Output
where
M: Any + Send + 'static;
}
impl<T> PyResultExt for PyResult<T> {
type Output = T;
#[inline] fn unwrap_unraisable_py_result<M>(
self,
py: Python<'_>,
obj: Option<&Bound<'_, PyAny>>,
msg: impl FnOnce() -> M,
) -> Self::Output
where
M: Any + Send + 'static,
{
match self {
Ok(v) => v,
Err(err) => {
err.write_unraisable(py, obj);
panic_any(msg());
}
}
}
}
macro_rules! delegate_inner {
($slf:expr, $func:ident, $($arg:expr),*) => {
$slf.0
.inner_ref()
.$func($($arg),*)
.map_err($crate::utils::TauriError::from)
.map_err(pyo3::PyErr::from)
};
}
pub(crate) use delegate_inner;
pub(crate) fn non_exhaustive_panic() -> ! {
panic!("NonExhaustive is reserved for `#[non_exhaustive]`");
}
macro_rules! cfg_impl {
(|$cfg:meta| -> $ty:ty $body:block) => {
{
let ret: ::pyo3::PyResult::<$ty> = {
#[cfg($cfg)]
$body
#[cfg(not($cfg))]
{
use pyo3::exceptions::PyNotImplementedError;
const MSG: &str = concat!("Available on pytauri `#[cfg(", stringify!($cfg), ")]` only.");
Err(PyNotImplementedError::new_err(MSG))
}
};
ret
}
};
}
pub(crate) use cfg_impl;