viaduct/
error.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5pub type Result<T, E = ViaductError> = std::result::Result<T, E>;
6
7#[derive(Debug, thiserror::Error, uniffi::Error)]
8pub enum ViaductError {
9    #[error("[no-sentry] Illegal characters in request header '{0}'")]
10    RequestHeaderError(String),
11
12    #[error("[no-sentry] Backend error: {0}")]
13    BackendError(String),
14
15    #[error("[no-sentry] Network error: {0}")]
16    NetworkError(String),
17
18    #[error("The rust-components network backend only be initialized once!")]
19    BackendAlreadyInitialized,
20
21    #[error("The rust-components network backend must be initialized before use!")]
22    BackendNotInitialized,
23
24    #[error("Backend already initialized.")]
25    SetBackendError,
26
27    /// Note: we return this if the server returns a bad URL with
28    /// its response. This *probably* should never happen, but who knows.
29    #[error("[no-sentry] URL Parse Error: {0}")]
30    UrlError(String),
31
32    #[error("[no-sentry] Validation error: URL does not use TLS protocol.")]
33    NonTlsUrl,
34
35    #[error("OHTTP channel '{0}' is not configured")]
36    OhttpChannelNotConfigured(String),
37
38    #[error("Failed to fetch OHTTP config: {0}")]
39    OhttpConfigFetchFailed(String),
40
41    #[error("OHTTP request error: {0}")]
42    OhttpRequestError(String),
43
44    #[error("OHTTP response error: {0}")]
45    OhttpResponseError(String),
46
47    #[error("OHTTP support is not enabled in this build")]
48    OhttpNotSupported,
49}
50
51impl ViaductError {
52    pub fn new_backend_error(msg: impl Into<String>) -> Self {
53        Self::BackendError(msg.into())
54    }
55}
56
57impl From<url::ParseError> for ViaductError {
58    fn from(e: url::ParseError) -> Self {
59        ViaductError::UrlError(e.to_string())
60    }
61}
62
63/// This error is returned as the `Err` result from
64/// [`Response::require_success`].
65///
66/// Note that it's not a variant on `Error` to distinguish between errors
67/// caused by the network, and errors returned from the server.
68#[derive(thiserror::Error, Debug, Clone)]
69#[error("Error: {method} {url} returned {status}")]
70pub struct UnexpectedStatus {
71    pub status: u16,
72    pub method: crate::Method,
73    pub url: url::Url,
74}
75
76/// Map errors from external crates like `tokio` and `hyper` to `Error::BackendError`
77///
78/// This works for any error that implements ToString
79pub trait MapBackendError {
80    type Ok;
81
82    fn map_backend_error(self) -> Result<Self::Ok>;
83}
84
85impl<T, E: ToString> MapBackendError for std::result::Result<T, E> {
86    type Ok = T;
87
88    fn map_backend_error(self) -> Result<T> {
89        self.map_err(|e| ViaductError::BackendError(e.to_string()))
90    }
91}
92
93/// Implement From<UnexpectedUniFFICallbackError> so that unexpected errors when invoking backend
94/// callback interface methods get converted to `BackendError`.
95impl From<uniffi::UnexpectedUniFFICallbackError> for ViaductError {
96    fn from(error: uniffi::UnexpectedUniFFICallbackError) -> Self {
97        ViaductError::BackendError(error.to_string())
98    }
99}