Skip to main content

tauri_plugin_notifications/
error.rs

1use serde::{ser::Serializer, Serialize};
2
3pub type Result<T> = std::result::Result<T, Error>;
4
5/// Replica of the tauri::plugin::mobile::ErrorResponse for desktop platforms.
6#[cfg(desktop)]
7#[derive(Debug, thiserror::Error, Clone, serde::Deserialize)]
8pub struct ErrorResponse<T = ()> {
9    /// Error code.
10    pub code: Option<String>,
11    /// Error message.
12    pub message: Option<String>,
13    /// Optional error data.
14    #[serde(flatten)]
15    pub data: T,
16}
17
18#[cfg(desktop)]
19impl<T> std::fmt::Display for ErrorResponse<T> {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        if let Some(code) = &self.code {
22            write!(f, "[{code}]")?;
23            if self.message.is_some() {
24                write!(f, " - ")?;
25            }
26        }
27        if let Some(message) = &self.message {
28            write!(f, "{message}")?;
29        }
30        Ok(())
31    }
32}
33
34/// Replica of the tauri::plugin::mobile::PluginInvokeError for desktop platforms.
35#[cfg(desktop)]
36#[derive(Debug, thiserror::Error)]
37pub enum PluginInvokeError {
38    /// Error returned from direct desktop plugin.
39    #[error(transparent)]
40    InvokeRejected(#[from] ErrorResponse),
41    /// Failed to deserialize response.
42    #[error("failed to deserialize response: {0}")]
43    CannotDeserializeResponse(serde_json::Error),
44    /// Failed to serialize request payload.
45    #[error("failed to serialize payload: {0}")]
46    CannotSerializePayload(serde_json::Error),
47}
48
49#[derive(Debug, thiserror::Error)]
50pub enum Error {
51    #[error(transparent)]
52    Io(#[from] std::io::Error),
53    #[cfg(mobile)]
54    #[error(transparent)]
55    PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
56    #[cfg(desktop)]
57    #[error(transparent)]
58    PluginInvoke(#[from] crate::error::PluginInvokeError),
59}
60
61impl Serialize for Error {
62    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
63    where
64        S: Serializer,
65    {
66        serializer.serialize_str(self.to_string().as_ref())
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use std::io;
74
75    #[test]
76    fn test_io_error_conversion() {
77        let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
78        let err: Error = io_err.into();
79        assert!(matches!(err, Error::Io(_)));
80    }
81
82    #[test]
83    fn test_io_error_serialization() {
84        let io_err = io::Error::new(io::ErrorKind::PermissionDenied, "access denied");
85        let err = Error::Io(io_err);
86        let json = serde_json::to_string(&err).expect("Failed to serialize IO error");
87        assert!(json.contains("access denied"));
88    }
89
90    #[test]
91    fn test_io_error_display() {
92        let io_err = io::Error::new(io::ErrorKind::NotFound, "test error");
93        let err = Error::Io(io_err);
94        let display_str = format!("{}", err);
95        assert!(display_str.contains("test error"));
96    }
97
98    #[cfg(mobile)]
99    #[test]
100    fn test_plugin_invoke_error_conversion() {
101        use tauri::plugin::mobile::PluginInvokeError;
102
103        let plugin_err = PluginInvokeError::MethodNotFound("test_method".to_string());
104        let err: Error = plugin_err.into();
105        assert!(matches!(err, Error::PluginInvoke(_)));
106    }
107
108    #[test]
109    fn test_result_type_err() {
110        let io_err = io::Error::other("test");
111        let result: Result<i32> = Err(Error::Io(io_err));
112        assert!(result.is_err());
113    }
114}