bitwarden_uniffi_error/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::sync::OnceLock;
4
5#[allow(clippy::type_complexity)]
6static ERROR_TO_UNIFFI_ERROR: OnceLock<
7    Box<dyn Fn(Box<dyn std::error::Error + Send + Sync>) -> anyhow::Error + Send + Sync + 'static>,
8> = OnceLock::new();
9
10pub use anyhow::Error;
11
12/// Configure an error converter to convert errors in calls to [`uniffi::custom_type!`] into the
13/// main error of the application (`bitwarden_uniffi::error::BitwardenError). This is needed because
14/// if the errors don't match, Uniffi will panic instead of returning an error. This needs to be
15/// called by the `bitwarden_uniffi` crate before any other Uniffi code is run.
16pub fn set_error_to_uniffi_error<F>(f: F)
17where
18    F: Fn(Box<dyn std::error::Error + Send + Sync>) -> anyhow::Error + Send + Sync + 'static,
19{
20    let _ = ERROR_TO_UNIFFI_ERROR.set(Box::new(f));
21}
22
23fn convert_error<E: std::error::Error + Send + Sync + 'static>(error: E) -> anyhow::Error {
24    if let Some(f) = ERROR_TO_UNIFFI_ERROR.get() {
25        f(Box::new(error))
26    } else {
27        anyhow::Error::new(error)
28    }
29}
30
31/// Convert a `Result` into one that will not cause a panic when called inside
32/// [`uniffi::custom_type!`]. It is required that all the results created inside a `custom_type!`
33/// are converted using this function.
34pub fn convert_result<T, E: std::error::Error + Send + Sync + 'static>(
35    result: Result<T, E>,
36) -> Result<T, anyhow::Error> {
37    result.map_err(|e| convert_error(e))
38}